View Javadoc

1   // SimpleCompiler.java, created Thu Mar  6  0:42:32 2003 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Compiler.Quad.x86;
5   
6   import java.util.Arrays;
7   import java.util.HashMap;
8   import java.util.HashSet;
9   import java.util.Iterator;
10  import java.util.LinkedList;
11  import java.util.List;
12  import java.util.Map;
13  import java.util.Set;
14  import joeq.Allocator.CodeAllocator;
15  import joeq.Allocator.DefaultCodeAllocator;
16  import joeq.Allocator.DefaultHeapAllocator;
17  import joeq.Allocator.HeapAllocator;
18  import joeq.Allocator.ObjectLayout;
19  import joeq.Assembler.Code2CodeReference;
20  import joeq.Assembler.Code2HeapReference;
21  import joeq.Assembler.DirectBindCall;
22  import joeq.Assembler.x86.x86;
23  import joeq.Assembler.x86.x86Assembler;
24  import joeq.Assembler.x86.x86Constants;
25  import joeq.Bootstrap.BootstrapCodeAllocator;
26  import joeq.Bootstrap.SinglePassBootImage;
27  import joeq.Class.jq_Array;
28  import joeq.Class.jq_Class;
29  import joeq.Class.jq_CompiledCode;
30  import joeq.Class.jq_InstanceField;
31  import joeq.Class.jq_InstanceMethod;
32  import joeq.Class.jq_Method;
33  import joeq.Class.jq_Primitive;
34  import joeq.Class.jq_StaticField;
35  import joeq.Class.jq_StaticMethod;
36  import joeq.Class.jq_TryCatch;
37  import joeq.Class.jq_Type;
38  import joeq.ClassLib.ClassLibInterface;
39  import joeq.Compiler.CompilerInterface;
40  import joeq.Compiler.BytecodeAnalysis.BytecodeVisitor;
41  import joeq.Compiler.Quad.BasicBlock;
42  import joeq.Compiler.Quad.BasicBlockVisitor;
43  import joeq.Compiler.Quad.CodeCache;
44  import joeq.Compiler.Quad.ControlFlowGraph;
45  import joeq.Compiler.Quad.ExceptionHandler;
46  import joeq.Compiler.Quad.ExceptionHandlerList;
47  import joeq.Compiler.Quad.Operand;
48  import joeq.Compiler.Quad.Quad;
49  import joeq.Compiler.Quad.QuadIterator;
50  import joeq.Compiler.Quad.QuadVisitor;
51  import joeq.Compiler.Quad.RegisterFactory;
52  import joeq.Compiler.Quad.Operand.AConstOperand;
53  import joeq.Compiler.Quad.Operand.BasicBlockTableOperand;
54  import joeq.Compiler.Quad.Operand.Const4Operand;
55  import joeq.Compiler.Quad.Operand.Const8Operand;
56  import joeq.Compiler.Quad.Operand.ParamListOperand;
57  import joeq.Compiler.Quad.Operand.RegisterOperand;
58  import joeq.Compiler.Quad.Operator.ALength;
59  import joeq.Compiler.Quad.Operator.ALoad;
60  import joeq.Compiler.Quad.Operator.AStore;
61  import joeq.Compiler.Quad.Operator.Binary;
62  import joeq.Compiler.Quad.Operator.BoundsCheck;
63  import joeq.Compiler.Quad.Operator.CheckCast;
64  import joeq.Compiler.Quad.Operator.Getfield;
65  import joeq.Compiler.Quad.Operator.Getstatic;
66  import joeq.Compiler.Quad.Operator.Goto;
67  import joeq.Compiler.Quad.Operator.InstanceOf;
68  import joeq.Compiler.Quad.Operator.IntIfCmp;
69  import joeq.Compiler.Quad.Operator.Invoke;
70  import joeq.Compiler.Quad.Operator.Jsr;
71  import joeq.Compiler.Quad.Operator.LookupSwitch;
72  import joeq.Compiler.Quad.Operator.MemLoad;
73  import joeq.Compiler.Quad.Operator.MemStore;
74  import joeq.Compiler.Quad.Operator.Monitor;
75  import joeq.Compiler.Quad.Operator.Move;
76  import joeq.Compiler.Quad.Operator.New;
77  import joeq.Compiler.Quad.Operator.NewArray;
78  import joeq.Compiler.Quad.Operator.NullCheck;
79  import joeq.Compiler.Quad.Operator.Putfield;
80  import joeq.Compiler.Quad.Operator.Putstatic;
81  import joeq.Compiler.Quad.Operator.Ret;
82  import joeq.Compiler.Quad.Operator.Return;
83  import joeq.Compiler.Quad.Operator.Special;
84  import joeq.Compiler.Quad.Operator.StoreCheck;
85  import joeq.Compiler.Quad.Operator.TableSwitch;
86  import joeq.Compiler.Quad.Operator.Unary;
87  import joeq.Compiler.Quad.Operator.ZeroCheck;
88  import joeq.Compiler.Quad.RegisterFactory.Register;
89  import joeq.Compiler.Reference.x86.x86ReferenceCompiler;
90  import joeq.Compiler.Reference.x86.x86ReferenceLinker;
91  import joeq.Main.HostedVM;
92  import joeq.Main.jq;
93  import joeq.Memory.CodeAddress;
94  import joeq.Memory.HeapAddress;
95  import joeq.Runtime.ExceptionDeliverer;
96  import joeq.Runtime.MathSupport;
97  import joeq.Runtime.ObjectTraverser;
98  import joeq.Runtime.Reflection;
99  import joeq.Runtime.SystemInterface;
100 import joeq.Runtime.TypeCheck;
101 import joeq.Runtime.Unsafe;
102 import joeq.Scheduler.jq_x86RegisterState;
103 import jwutil.collections.AppendIterator;
104 import jwutil.strings.Strings;
105 import jwutil.util.Assert;
106 
107 /***
108  * @author John Whaley <jwhaley@alum.mit.edu>
109  * @version $Id: SimpleCompiler.java 1941 2004-09-30 03:37:06Z joewhaley $
110  */
111 public class SimpleCompiler implements x86Constants, BasicBlockVisitor, QuadVisitor {
112 
113     static {
114         // we are using x86, so initialize the register state factory.
115         jq_x86RegisterState.initFactory();
116     }
117     
118     public static class Factory implements CompilerInterface {
119         public static final Factory INSTANCE = new Factory();
120         public Factory() {}
121         public jq_CompiledCode compile(jq_Method m) {
122             return new SimpleCompiler(m).compile();
123         }
124         public jq_CompiledCode generate_compile_stub(jq_Method m) {
125             return x86ReferenceCompiler.generate_compile_stub(m);
126         }
127         public jq_StaticMethod getInvokestaticLinkMethod() {
128             return x86ReferenceLinker._invokestatic;
129         }
130         public jq_StaticMethod getInvokespecialLinkMethod() {
131             return x86ReferenceLinker._invokespecial;
132         }
133         public jq_StaticMethod getInvokeinterfaceLinkMethod() {
134             return x86ReferenceLinker._invokeinterface;
135         }
136     }
137     
138     public static /*final*/ boolean ALWAYS_TRACE = false;
139     public static /*final*/ boolean TRACE_STUBS = false;
140 
141     public static final Set TraceMethod_MethodNames = new HashSet();
142     public static final Set TraceMethod_ClassNames = new HashSet();
143     public static final Set TraceQuad_MethodNames = new HashSet();
144     public static final Set TraceQuad_ClassNames = new HashSet();
145     
146     public boolean TraceQuads;
147     public boolean TraceMethods;
148     public boolean TraceArguments;
149     
150     public static final int DEFAULT_ALIGNMENT = 32;
151     
152     public ControlFlowGraph cfg;
153     public jq_Method method;
154     public Map registerLocations;
155     
156     public boolean TRACE;
157     
158     public SimpleCompiler() { }
159     public SimpleCompiler(ControlFlowGraph cfg) { this.init(cfg); }
160     public SimpleCompiler(jq_Method m) { this.init(m); }
161     
162     public void init(jq_Method m) {
163         init(CodeCache.getCode(m));
164     }
165     
166     public void init(ControlFlowGraph cfg) {
167         this.cfg = cfg;
168         method = cfg.getMethod();
169         TRACE = ALWAYS_TRACE;
170         if (TraceQuad_MethodNames.contains(method.getName().toString())) {
171             TraceQuads = true;
172             TraceMethods = true;
173         } else if (TraceQuad_ClassNames.contains(method.getDeclaringClass().getName().toString())) {
174             TraceQuads = true;
175             TraceMethods = true;
176         } else if (TraceMethod_MethodNames.contains(method.getName().toString())) {
177             TraceQuads = false;
178             TraceMethods = true;
179         } else if (TraceMethod_ClassNames.contains(method.getDeclaringClass().getName().toString())) {
180             TraceQuads = false;
181             TraceMethods = true;
182         } else {
183             TraceQuads = false;
184             TraceMethods = false;
185         }
186         TraceArguments = false;
187         registerLocations = new HashMap();
188         code_relocs = new LinkedList();
189         data_relocs = new LinkedList();
190     }
191     
192     public String toString() {
193         return "x86Quad/"+Strings.left(method.getName().toString(), 10);
194     }
195     
196     private x86Assembler asm;   // Assembler to output to.
197     private int n_paramwords;   // number of words used by incoming parameters.
198 
199     private List code_relocs;
200     private List data_relocs;
201     
202     public final void emitCallRelative(jq_Method target) { emitCallRelative(target, asm, code_relocs); }
203     public static final void emitCallRelative(jq_Method target, x86Assembler asm, List code_relocs) {
204         asm.emitCALL_rel32(x86.CALL_rel32, 0);
205         DirectBindCall r = new DirectBindCall((CodeAddress) asm.getCurrentAddress().offset(-4), target);
206         code_relocs.add(r);
207         if (ALWAYS_TRACE) System.out.println("Direct bind call: "+r);
208     }
209     public final void emitPushAddressOf(Object o) { emitPushAddressOf(o, asm, data_relocs); }
210     public static final void emitPushAddressOf(Object o, x86Assembler asm, List data_relocs) {
211         if (o != null) {
212             HeapAddress addr = HeapAddress.addressOf(o);
213             asm.emit1_Imm32(x86.PUSH_i32, addr.to32BitValue());
214             Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
215             data_relocs.add(r);
216             if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
217         } else {
218             asm.emit1_Imm8(x86.PUSH_i8, (byte)0);
219         }
220     }
221     public final void emitPushMemory(jq_StaticField f) { emitPushMemory(f, asm, data_relocs); }
222     public static final void emitPushMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
223         HeapAddress addr = f.getAddress();
224         asm.emit2_Mem(x86.PUSH_m, addr.to32BitValue());
225         Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
226         data_relocs.add(r);
227         if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
228     }
229     public final void emitPushMemory8(jq_StaticField f) { emitPushMemory8(f, asm, data_relocs); }
230     public static final void emitPushMemory8(jq_StaticField f, x86Assembler asm, List data_relocs) {
231         HeapAddress addr = f.getAddress();
232         asm.emit2_Mem(x86.PUSH_m, addr.offset(4).to32BitValue()); // hi
233         Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), (HeapAddress) addr.offset(4));
234         data_relocs.add(r);
235         asm.emit2_Mem(x86.PUSH_m, addr.to32BitValue()); // lo
236         r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
237         data_relocs.add(r);
238         if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
239     }
240     public final void emitPopMemory(jq_StaticField f) { emitPopMemory(f, asm, data_relocs); }
241     public static final void emitPopMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
242         HeapAddress addr = f.getAddress();
243         asm.emit2_Mem(x86.POP_m, addr.to32BitValue());
244         Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
245         data_relocs.add(r);
246         if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
247     }
248     public final void emitPopMemory8(jq_StaticField f) { emitPopMemory8(f, asm, data_relocs); }
249     public static final void emitPopMemory8(jq_StaticField f, x86Assembler asm, List data_relocs) {
250         HeapAddress addr = f.getAddress();
251         asm.emit2_Mem(x86.POP_m, addr.to32BitValue()); // lo
252         Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
253         data_relocs.add(r);
254         if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
255         asm.emit2_Mem(x86.POP_m, addr.offset(4).to32BitValue()); // hi
256         r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), (HeapAddress) addr.offset(4));
257         data_relocs.add(r);
258         if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
259     }
260     public final void emitCallMemory(jq_StaticField f) { emitCallMemory(f, asm, data_relocs); }
261     public static final void emitCallMemory(jq_StaticField f, x86Assembler asm, List data_relocs) {
262         HeapAddress addr = f.getAddress();
263         asm.emit2_Mem(x86.CALL_m, addr.to32BitValue());
264         Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
265         data_relocs.add(r);
266         if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
267     }
268     public final void emitFLD64(jq_StaticField f) { emitFLD64(f, asm, data_relocs); }
269     public static final void emitFLD64(jq_StaticField f, x86Assembler asm, List data_relocs) {
270         HeapAddress addr = f.getAddress();
271         asm.emit2_Mem(x86.FLD_m64, addr.to32BitValue());
272         Code2HeapReference r = new Code2HeapReference((CodeAddress) asm.getCurrentAddress().offset(-4), addr);
273         data_relocs.add(r);
274         if (ALWAYS_TRACE) System.out.println("Code2Heap reference: "+r);
275     }
276     
277     public final List getCodeRelocs() { return code_relocs; }
278     public final List getDataRelocs() { return data_relocs; }
279     
280     public static final jq_CompiledCode generate_compile_stub(jq_Method method) {
281         if (TRACE_STUBS) System.out.println("x86 Quad Compiler: generating compile stub for "+method);
282         x86Assembler asm = new x86Assembler(0, 24, 0, DEFAULT_ALIGNMENT);
283         asm.setEntrypoint();
284         List code_relocs = new LinkedList();
285         List data_relocs = new LinkedList();
286         if (TRACE_STUBS) {
287             emitPushAddressOf(SystemInterface.toCString("Stub compile: "+method), asm, data_relocs);
288             emitCallMemory(SystemInterface._debugwriteln, asm, data_relocs);
289         }
290         emitPushAddressOf(method, asm, data_relocs);
291         emitCallRelative(jq_Method._compile, asm, code_relocs);
292         asm.emit2_Mem(x86.JMP_m, jq_CompiledCode._entrypoint.getOffset(), EAX);
293         // return generated code
294         return asm.getCodeBuffer().allocateCodeBlock(null, null, null, null, 0, code_relocs, data_relocs);
295     }
296     
297     int getParamOffset(int i) {
298         Assert._assert(i < n_paramwords);
299         return (n_paramwords-i+1)<<2;
300     }
301     
302     int getStackOffset(RegisterOperand r) { return getStackOffset(r.getRegister()); }
303     
304     int getStackOffset(Register r) {
305         Integer i = (Integer) registerLocations.get(r);
306         return i.intValue();
307     }
308     
309     int getStackFrameWords() {
310         return cfg.getRegisterFactory().size();
311     }
312     
313     void initializeRegisterLocations() {
314         int current = -((getStackFrameWords()) << 2);
315         RegisterFactory rf = cfg.getRegisterFactory();
316         for (Iterator i=rf.iterator(); i.hasNext(); current += 4) {
317             Register r = (Register) i.next();
318             registerLocations.put(r, new Integer(current));
319             if (TRACE) System.out.println("Register: "+r+" offset: "+current);
320         }
321         Assert._assert(current == 0);
322     }
323     
324     // Generate code for the given method.
325     public final jq_CompiledCode compile() {
326         if (TRACE) System.out.println("x86 Quad Compiler: compiling "+method);
327         
328         // temporary kludge: no switching a thread during compilation.
329         if (jq.RunningNative)
330             Unsafe.getThreadBlock().disableThreadSwitch();
331         
332         try {
333             // initialize stuff
334             this.initializeRegisterLocations();
335             
336             int quadcount = 0;
337             for (QuadIterator i=new QuadIterator(cfg); i.hasNext(); i.next())
338                 ++quadcount;
339             
340             asm = new x86Assembler(quadcount, quadcount*8, 5, DEFAULT_ALIGNMENT);
341             asm.skip(5); // space for jump point
342             asm.setEntrypoint();
343             jq_Type[] params = method.getParamTypes();
344             n_paramwords = method.getParamWords();
345             int n_localwords = getStackFrameWords();
346             
347             // stack frame before prolog:
348             // b0: FP->| caller's saved FP  |
349             // ac:     | caller's locals    |
350             //         |        ...         |
351             // 94:     | caller's opstack   |
352             //         |        ...         |
353             // 80:     | pushed params      |
354             //         |        ...         |
355             // 74: SP->| ret addr in caller |
356             
357             // emit prolog
358             asm.emitShort_Reg(x86.PUSH_r, EBP);         // push old FP
359             asm.emit2_Reg_Reg(x86.MOV_r_r32, EBP, ESP); // set new FP
360             asm.emit2_Reg_Mem(x86.LEA, ESP, -n_localwords<<2, ESP);
361             
362             // stack frame after prolog:
363             // b0:     | caller's saved FP  |
364             // ac:     | caller's locals    |
365             //         |        ...         |
366             // 94:     | caller's opstack   |
367             //         |        ...         |
368             // 80:     | pushed params      |
369             //         |        ...         |
370             // 74:     | ret addr in caller |
371             // 70: FP->| callee's FP (b0)   |
372             // 6c:     | callee's locals    |
373             //     SP->|        ...         |
374     
375             // print a debug message
376             if (TraceMethods) {
377                 emitPushAddressOf(SystemInterface.toCString("Entering: "+method));
378                 emitCallMemory(SystemInterface._debugwriteln);
379             }
380             
381             RegisterFactory rf = cfg.getRegisterFactory();
382             for (int i=0, j=0; i<params.length; ++i, ++j) {
383                 if (params[i].getReferenceSize() == 8) {
384                     int param_offset = getParamOffset(j+1); // lo
385                     int stack_offset = getStackOffset(rf.getOrCreateLocal(j, params[i])); // lo
386                     asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, param_offset, EBP);
387                     asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, stack_offset, EBP);
388                     param_offset = getParamOffset(j); // hi
389                     stack_offset = getStackOffset(rf.getOrCreateLocal(j+1, params[i])); // hi
390                     asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, param_offset, EBP);
391                     asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, stack_offset, EBP);
392                     ++j;
393                 } else {
394                     int param_offset = getParamOffset(j);
395                     int stack_offset = getStackOffset(rf.getOrCreateLocal(j, params[i]));
396                     asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, param_offset, EBP);
397                     asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, stack_offset, EBP);
398                 }
399             }
400             
401             // add monitorenter for synchronized methods.
402             if (method.isSynchronized()) {
403                 if (method.isStatic()) {
404                     if (TraceQuads) {
405                         emitPushAddressOf(SystemInterface.toCString("entry: STATIC SYNCH ENTER"));
406                         emitCallMemory(SystemInterface._debugwriteln);
407                     }
408                     // lock the java.lang.Class object
409                     Class c = Reflection.getJDKType(method.getDeclaringClass());
410                     Assert._assert(c != null);
411                     emitPushAddressOf(c);
412                 } else {
413                     if (TraceQuads) {
414                         emitPushAddressOf(SystemInterface.toCString("entry: INSTANCE SYNCH ENTER"));
415                         emitCallMemory(SystemInterface._debugwriteln);
416                     }
417                     // lock the this pointer
418                     asm.emit2_Mem(x86.PUSH_m, getParamOffset(0), EBP);
419                 }
420                 emitCallRelative(joeq.Runtime.Monitor._monitorenter);
421             }
422             
423             // generate code for each quad in order
424             cfg.visitBasicBlocks(this);
425     
426             // generate exception table
427             List tcs = new LinkedList();
428             for (Iterator i=cfg.reversePostOrderIterator(); i.hasNext(); ) {
429                 BasicBlock bb = (BasicBlock) i.next();
430                 ExceptionHandlerList ex = bb.getExceptionHandlers();
431                 int start = asm.getBranchTarget(bb);
432                 int end = asm.getBranchTarget(new Integer(bb.getID()));
433                 for (Iterator j=ex.exceptionHandlerIterator(); j.hasNext(); ) {
434                     ExceptionHandler e = (ExceptionHandler) j.next();
435                     int handler = asm.getBranchTarget(e.getEntry());
436                     Iterator k = e.getEntry().iterator();
437                     Assert._assert(k.hasNext());
438                     Quad x = (Quad) k.next();
439                     Assert._assert(x.getOperator() instanceof Special.GET_EXCEPTION);
440                     RegisterOperand rop = (RegisterOperand) Special.getOp1(x);
441                     jq_TryCatch tc = new jq_TryCatch(start, end, handler, e.getExceptionType(), getStackOffset(rop));
442                     tcs.add(tc);
443                 }
444             }
445             jq_TryCatch[] tcs_a = (jq_TryCatch[]) tcs.toArray(new jq_TryCatch[tcs.size()]);
446             
447             // TODO: generate bytecode map
448             
449             // return generated code
450             jq_CompiledCode code;
451             code = asm.getCodeBuffer().allocateCodeBlock(method, tcs_a, null,
452                                                          x86QuadExceptionDeliverer.INSTANCE,
453                                                          n_localwords*4,
454                                                          code_relocs, data_relocs);
455             CodeCache.free(cfg);
456             // temporary kludge: no switching a thread during compilation.
457             if (jq.RunningNative)
458                 Unsafe.getThreadBlock().enableThreadSwitch();
459             return code;
460         } catch (RuntimeException x) {
461             SystemInterface.debugwriteln("Exception occurred while compiling: "+method);
462             SystemInterface.debugwriteln("Exception: "+x);
463             x.printStackTrace();
464             SystemInterface.die(-1);
465             return null;
466         }
467     }
468     
469     public void visitBasicBlock(BasicBlock bb) {
470         // record start of basic block
471         asm.recordBranchTarget(bb);
472         // resolve forward branches to this block
473         asm.resolveForwardBranches(bb);
474         // generate code for this block
475         for (joeq.Util.Templates.ListIterator.Quad i=bb.iterator(); i.hasNext(); ) {
476             this.handled = false;
477             Quad q = i.nextQuad();
478             q.accept(this);
479             Assert._assert(handled, q.toString());
480         }
481         if (bb.getFallthroughSuccessor() != null)
482             branchHelper(BytecodeVisitor.CMP_UNCOND, bb.getFallthroughSuccessor());
483         // record end of basic block (for exception handler ranges)
484         asm.recordBranchTarget(new Integer(bb.getID()));
485     }
486     
487     public static byte THREAD_BLOCK_PREFIX = x86.PREFIX_FS;
488     public static int  THREAD_BLOCK_OFFSET = 0x14;
489 
490     private int getPairedRegister(int register) {
491         switch (register) {
492         case EAX: return EDX;
493         case EBX: return ECX;
494         case ECX: return EBX;
495         case EDX: return EAX;
496         default: Assert.UNREACHABLE(); return 0;
497         }
498     }
499     
500     private void loadOperand(Operand o, int register) {
501         if (o instanceof RegisterOperand) {
502             int src = getStackOffset((RegisterOperand) o);
503             asm.emit2_Reg_Mem(x86.MOV_r_m32, register, src, EBP);
504             if (((RegisterOperand) o).getType().getReferenceSize() == 8) {
505                 asm.emit2_Reg_Mem(x86.MOV_r_m32, getPairedRegister(register), src+4, EBP);
506             }
507         } else if (o instanceof AConstOperand) {
508             Object a = ((AConstOperand) o).getValue();
509             emitPushAddressOf(a);
510             asm.emitShort_Reg(x86.POP_r, register);
511         } else if (o instanceof Const4Operand) {
512             int v = ((Const4Operand) o).getBits();
513             asm.emitShort_Reg_Imm(x86.MOV_r_i32, register, v);
514         } else if (o instanceof Const8Operand) {
515             long v = ((Const8Operand) o).getBits();
516             asm.emitShort_Reg_Imm(x86.MOV_r_i32, register, (int)(v));                        // lo
517             asm.emitShort_Reg_Imm(x86.MOV_r_i32, getPairedRegister(register), (int)(v>>32)); // hi
518         } else {
519             Assert.UNREACHABLE("x86 register "+register+": "+o);
520         }
521     }
522     
523     private void storeOperand(RegisterOperand o, int register) {
524         int dest = getStackOffset(o);
525         asm.emit2_Reg_Mem(x86.MOV_m_r32, register, dest, EBP);
526         if (o.getType().getReferenceSize() == 8) {
527             asm.emit2_Reg_Mem(x86.MOV_m_r32, getPairedRegister(register), dest+4, EBP); // hi
528         }
529     }
530     
531     /***
532      * @see joeq.Compiler.Quad.QuadVisitor#visitExceptionThrower(joeq.Compiler.Quad.Quad)
533      */
534     public void visitExceptionThrower(Quad obj) {
535         if (TRACE) System.out.println(this+" PEI: "+obj);
536     }
537     /***
538      * @see joeq.Compiler.Quad.QuadVisitor#visitLoad(joeq.Compiler.Quad.Quad)
539      */
540     public void visitLoad(Quad obj) {
541         if (TRACE) System.out.println(this+" Load: "+obj);
542     }
543     /***
544      * @see joeq.Compiler.Quad.QuadVisitor#visitStore(joeq.Compiler.Quad.Quad)
545      */
546     public void visitStore(Quad obj) {
547         if (TRACE) System.out.println(this+" Store: "+obj);
548     }
549     /***
550      * @see joeq.Compiler.Quad.QuadVisitor#visitBranch(joeq.Compiler.Quad.Quad)
551      */
552     public void visitBranch(Quad obj) {
553         if (TRACE) System.out.println(this+" Branch: "+obj);
554     }
555     /***
556      * @see joeq.Compiler.Quad.QuadVisitor#visitCondBranch(joeq.Compiler.Quad.Quad)
557      */
558     public void visitCondBranch(Quad obj) {
559         if (TRACE) System.out.println(this+" CondBranch: "+obj);
560     }
561     /***
562      * @see joeq.Compiler.Quad.QuadVisitor#visitCheck(joeq.Compiler.Quad.Quad)
563      */
564     public void visitCheck(Quad obj) {
565         if (TRACE) System.out.println(this+" Check: "+obj);
566     }
567     /***
568      * @see joeq.Compiler.Quad.QuadVisitor#visitStaticField(joeq.Compiler.Quad.Quad)
569      */
570     public void visitStaticField(Quad obj) {
571         if (TRACE) System.out.println(this+" StaticField: "+obj);
572     }
573     /***
574      * @see joeq.Compiler.Quad.QuadVisitor#visitInstanceField(joeq.Compiler.Quad.Quad)
575      */
576     public void visitInstanceField(Quad obj) {
577         if (TRACE) System.out.println(this+" InstanceField: "+obj);
578     }
579     /***
580      * @see joeq.Compiler.Quad.QuadVisitor#visitArray(joeq.Compiler.Quad.Quad)
581      */
582     public void visitArray(Quad obj) {
583         if (TRACE) System.out.println(this+" Array: "+obj);
584     }
585     /***
586      * @see joeq.Compiler.Quad.QuadVisitor#visitAllocation(joeq.Compiler.Quad.Quad)
587      */
588     public void visitAllocation(Quad obj) {
589         if (TRACE) System.out.println(this+" Allocation: "+obj);
590     }
591     /***
592      * @see joeq.Compiler.Quad.QuadVisitor#visitTypeCheck(joeq.Compiler.Quad.Quad)
593      */
594     public void visitTypeCheck(Quad obj) {
595         if (TRACE) System.out.println(this+" TypeCheck: "+obj);
596     }
597     /***
598      * @see joeq.Compiler.Quad.QuadVisitor#visitALoad(joeq.Compiler.Quad.Quad)
599      */
600     public void visitALoad(Quad obj) {
601         if (TRACE) System.out.println(this+" ALoad: "+obj);
602         loadOperand(ALoad.getBase(obj), EAX);
603         loadOperand(ALoad.getIndex(obj), EBX);
604         jq_Type t = ((ALoad) obj.getOperator()).getType();
605         int scale = t.getReferenceSize();
606         switch (scale) {
607         case 4:
608             asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, EAX, EBX, SCALE_4, ObjectLayout.ARRAY_ELEMENT_OFFSET);
609             break;
610         case 2:
611             if (t == jq_Primitive.CHAR)
612                 asm.emit3_Reg_Mem(x86.MOVZX_r_m16, ECX, EAX, EBX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
613             else
614                 asm.emit3_Reg_Mem(x86.MOVSX_r_m16, ECX, EAX, EBX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
615             break;
616         case 1:
617             asm.emit3_Reg_Mem(x86.MOVSX_r_m8, ECX, EAX, EBX, SCALE_1, ObjectLayout.ARRAY_ELEMENT_OFFSET);
618             break;
619         case 8:
620             asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET);   // lo
621             asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, EAX, EBX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET+4); // hi
622             break;
623         default: Assert.UNREACHABLE(); break;
624         }
625         storeOperand(ALoad.getDest(obj), ECX);
626         this.handled = true;
627     }
628     /***
629      * @see joeq.Compiler.Quad.QuadVisitor#visitAStore(joeq.Compiler.Quad.Quad)
630      */
631     public void visitAStore(Quad obj) {
632         if (TRACE) System.out.println(this+" AStore: "+obj);
633         
634         loadOperand(AStore.getBase(obj), EAX);
635         loadOperand(AStore.getIndex(obj), EDX);
636         loadOperand(AStore.getValue(obj), ECX);
637         
638         jq_Type t = ((AStore) obj.getOperator()).getType();
639         int scale = t.getReferenceSize();
640         switch (scale) {
641         case 4:
642             asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EDX, SCALE_4, ObjectLayout.ARRAY_ELEMENT_OFFSET);
643             break;
644         case 2:
645             asm.emitprefix(x86.PREFIX_16BIT);
646             asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EDX, SCALE_2, ObjectLayout.ARRAY_ELEMENT_OFFSET);
647             break;
648         case 1:
649             asm.emit2_Reg_Mem(x86.MOV_m_r8, ECX, EAX, EDX, SCALE_1, ObjectLayout.ARRAY_ELEMENT_OFFSET);
650             break;
651         case 8:
652             asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, EAX, EDX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET  ); // lo
653             asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, EAX, EDX, SCALE_8, ObjectLayout.ARRAY_ELEMENT_OFFSET+4); // hi
654             break;
655         default: Assert.UNREACHABLE(); break;
656         }
657         this.handled = true;
658     }
659     /***
660      * @see joeq.Compiler.Quad.QuadVisitor#visitALength(joeq.Compiler.Quad.Quad)
661      */
662     public void visitALength(Quad obj) {
663         if (TRACE) System.out.println(this+" ALength: "+obj);
664         loadOperand(ALength.getSrc(obj), EAX);
665         asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
666         storeOperand(ALength.getDest(obj), EAX);
667         this.handled = true;
668     }
669     /***
670      * @see joeq.Compiler.Quad.QuadVisitor#visitBinary(joeq.Compiler.Quad.Quad)
671      */
672     public void visitBinary(Quad obj) {
673         if (TRACE) System.out.println(this+" Binary: "+obj);
674         loadOperand(Binary.getSrc1(obj), EAX);
675         loadOperand(Binary.getSrc2(obj), EBX);
676         Binary op = (Binary) obj.getOperator();
677         if (op instanceof Binary.ADD_I || op instanceof Binary.ADD_P) {
678             asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, EBX);
679         } else if (op instanceof Binary.SUB_I || op instanceof Binary.SUB_P) {
680             asm.emitARITH_Reg_Reg(x86.SUB_r_r32, EAX, EBX);
681         } else if (op instanceof Binary.MUL_I) {
682             asm.emit2_Reg(x86.IMUL_rda_r32, EBX);
683         } else if (op instanceof Binary.DIV_I) {
684             asm.emit1(x86.CWD);
685             asm.emit2_Reg(x86.IDIV_r32, EBX);
686         } else if (op instanceof Binary.REM_I) {
687             asm.emit1(x86.CWD);
688             asm.emit2_Reg(x86.IDIV_r32, EBX);
689             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDX);
690         } else if (op instanceof Binary.AND_I) {
691             asm.emitARITH_Reg_Reg(x86.AND_r_r32, EAX, EBX);
692         } else if (op instanceof Binary.OR_I) {
693             asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, EBX);
694         } else if (op instanceof Binary.XOR_I) {
695             asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EBX);
696         } else if (op instanceof Binary.ADD_L) {
697             asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, EBX);
698             asm.emitARITH_Reg_Reg(x86.ADC_r_r32, EDX, ECX);
699         } else if (op instanceof Binary.SUB_L) {
700             asm.emitARITH_Reg_Reg(x86.SUB_r_r32, EAX, EBX);
701             asm.emitARITH_Reg_Reg(x86.SBB_r_r32, EDX, ECX);
702         } else if (op instanceof Binary.MUL_L) {
703             asm.emit2_Reg_Reg(x86.MOV_r_r32, ESI, EAX);
704             asm.emit2_Reg_Reg(x86.MOV_r_r32, EDI, EDX);
705             asm.emitARITH_Reg_Reg(x86.OR_r_r32, EDX, ECX); // hi1 | hi2
706             asm.emitCJUMP_Short(x86.JNE, (byte)0);
707             int cloc = asm.getCurrentOffset();
708             asm.emit2_Reg(x86.MUL_rda_r32, EBX); // lo1*lo2
709             asm.emitJUMP_Short(x86.JMP, (byte)0);
710             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
711             cloc = asm.getCurrentOffset();
712             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI); // lo2
713             asm.emit2_Reg(x86.MUL_rda_r32, ECX); // hi1*lo2
714             asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EAX); // hi1*lo2
715             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDI); // hi2
716             asm.emit2_Reg(x86.MUL_rda_r32, EBX); // hi2*lo1
717             asm.emitARITH_Reg_Reg(x86.ADD_r_r32, ECX, EAX); // hi2*lo1 + hi1*lo2
718             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ESI); // lo2
719             asm.emit2_Reg(x86.MUL_rda_r32, EBX); // lo1*lo2
720             asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EDX, ECX); // hi2*lo1 + hi1*lo2 + hi(lo1*lo2)
721             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
722         } else if (op instanceof Binary.DIV_L) {
723             asm.emitShort_Reg(x86.PUSH_r, EDX);
724             asm.emitShort_Reg(x86.PUSH_r, EAX);
725             asm.emitShort_Reg(x86.PUSH_r, ECX);
726             asm.emitShort_Reg(x86.PUSH_r, EBX);
727             emitCallRelative(MathSupport._ldiv);
728         } else if (op instanceof Binary.REM_L) {
729             asm.emitShort_Reg(x86.PUSH_r, EDX);
730             asm.emitShort_Reg(x86.PUSH_r, EAX);
731             asm.emitShort_Reg(x86.PUSH_r, ECX);
732             asm.emitShort_Reg(x86.PUSH_r, EBX);
733             emitCallRelative(MathSupport._lrem);
734         } else if (op instanceof Binary.AND_L) {
735             asm.emitARITH_Reg_Reg(x86.AND_r_r32, EAX, EBX);
736             asm.emitARITH_Reg_Reg(x86.AND_r_r32, EDX, ECX);
737         } else if (op instanceof Binary.OR_L) {
738             asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, EBX);
739             asm.emitARITH_Reg_Reg(x86.OR_r_r32, EDX, ECX);
740         } else if (op instanceof Binary.XOR_L) {
741             asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EBX);
742             asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EDX, ECX);
743         } else if (op instanceof Binary.ADD_F) {
744             asm.emitShort_Reg(x86.PUSH_r, EAX);
745             asm.emitShort_Reg(x86.PUSH_r, EBX);
746             asm.emit2_Mem(x86.FLD_m32, 4, ESP);
747             asm.emit2_Mem(x86.FADD_m32, 0, ESP);
748             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
749             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
750             asm.emitShort_Reg(x86.POP_r, EAX);
751         } else if (op instanceof Binary.SUB_F) {
752             asm.emitShort_Reg(x86.PUSH_r, EAX);
753             asm.emitShort_Reg(x86.PUSH_r, EBX);
754             asm.emit2_Mem(x86.FLD_m32, 4, ESP);
755             asm.emit2_Mem(x86.FSUB_m32, 0, ESP);
756             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
757             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
758             asm.emitShort_Reg(x86.POP_r, EAX);
759         } else if (op instanceof Binary.MUL_F) {
760             asm.emitShort_Reg(x86.PUSH_r, EAX);
761             asm.emitShort_Reg(x86.PUSH_r, EBX);
762             asm.emit2_Mem(x86.FLD_m32, 4, ESP);
763             asm.emit2_Mem(x86.FMUL_m32, 0, ESP);
764             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
765             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
766             asm.emitShort_Reg(x86.POP_r, EAX);
767         } else if (op instanceof Binary.DIV_F) {
768             asm.emitShort_Reg(x86.PUSH_r, EAX);
769             asm.emitShort_Reg(x86.PUSH_r, EBX);
770             asm.emit2_Mem(x86.FLD_m32, 4, ESP);
771             asm.emit2_Mem(x86.FDIV_m32, 0, ESP);
772             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
773             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
774             asm.emitShort_Reg(x86.POP_r, EAX);
775         } else if (op instanceof Binary.REM_F) {
776             asm.emitShort_Reg(x86.PUSH_r, EAX);
777             asm.emitShort_Reg(x86.PUSH_r, EBX);
778             asm.emit2_Mem(x86.FLD_m32, 0, ESP); // reverse because pushing on fp stack
779             asm.emit2_Mem(x86.FLD_m32, 4, ESP);
780             asm.emit2(x86.FPREM);
781             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
782             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
783             asm.emit2_FPReg(x86.FFREE, 0);
784             asm.emitShort_Reg(x86.POP_r, EAX);
785         } else if (op instanceof Binary.ADD_D) {
786             asm.emitShort_Reg(x86.PUSH_r, EDX);
787             asm.emitShort_Reg(x86.PUSH_r, EAX);
788             asm.emitShort_Reg(x86.PUSH_r, ECX);
789             asm.emitShort_Reg(x86.PUSH_r, EBX);
790             asm.emit2_Mem(x86.FLD_m64, 8, ESP);
791             asm.emit2_Mem(x86.FADD_m64, 0, ESP);
792             asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
793             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
794             asm.emitShort_Reg(x86.POP_r, EAX);
795             asm.emitShort_Reg(x86.POP_r, EDX);
796         } else if (op instanceof Binary.SUB_D) {
797             asm.emitShort_Reg(x86.PUSH_r, EDX);
798             asm.emitShort_Reg(x86.PUSH_r, EAX);
799             asm.emitShort_Reg(x86.PUSH_r, ECX);
800             asm.emitShort_Reg(x86.PUSH_r, EBX);
801             asm.emit2_Mem(x86.FLD_m64, 8, ESP);
802             asm.emit2_Mem(x86.FSUB_m64, 0, ESP);
803             asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
804             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
805             asm.emitShort_Reg(x86.POP_r, EAX);
806             asm.emitShort_Reg(x86.POP_r, EDX);
807         } else if (op instanceof Binary.MUL_D) {
808             asm.emitShort_Reg(x86.PUSH_r, EDX);
809             asm.emitShort_Reg(x86.PUSH_r, EAX);
810             asm.emitShort_Reg(x86.PUSH_r, ECX);
811             asm.emitShort_Reg(x86.PUSH_r, EBX);
812             asm.emit2_Mem(x86.FLD_m64, 8, ESP);
813             asm.emit2_Mem(x86.FMUL_m64, 0, ESP);
814             asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
815             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
816             asm.emitShort_Reg(x86.POP_r, EAX);
817             asm.emitShort_Reg(x86.POP_r, EDX);
818         } else if (op instanceof Binary.DIV_D) {
819             asm.emitShort_Reg(x86.PUSH_r, EDX);
820             asm.emitShort_Reg(x86.PUSH_r, EAX);
821             asm.emitShort_Reg(x86.PUSH_r, ECX);
822             asm.emitShort_Reg(x86.PUSH_r, EBX);
823             asm.emit2_Mem(x86.FLD_m64, 8, ESP);
824             asm.emit2_Mem(x86.FDIV_m64, 0, ESP);
825             asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
826             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
827             asm.emitShort_Reg(x86.POP_r, EAX);
828             asm.emitShort_Reg(x86.POP_r, EDX);
829         } else if (op instanceof Binary.REM_D) {
830             asm.emitShort_Reg(x86.PUSH_r, EDX);
831             asm.emitShort_Reg(x86.PUSH_r, EAX);
832             asm.emitShort_Reg(x86.PUSH_r, ECX);
833             asm.emitShort_Reg(x86.PUSH_r, EBX);
834             asm.emit2_Mem(x86.FLD_m64, 0, ESP);
835             asm.emit2_Mem(x86.FLD_m64, 8, ESP);
836             asm.emit2(x86.FPREM);
837             asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
838             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
839             asm.emit2_FPReg(x86.FFREE, 0);
840             asm.emitShort_Reg(x86.POP_r, EAX);
841             asm.emitShort_Reg(x86.POP_r, EDX);
842         } else if (op instanceof Binary.SHL_I) {
843             asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
844             asm.emit2_Reg(x86.SHL_r32_rc, EAX);
845         } else if (op instanceof Binary.SHR_I) {
846             asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
847             asm.emit2_Reg(x86.SAR_r32_rc, EAX);
848         } else if (op instanceof Binary.USHR_I) {
849             asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
850             asm.emit2_Reg(x86.SHR_r32_rc, EAX);
851         } else if (op instanceof Binary.SHL_L) {
852             asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
853             asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
854             asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
855             asm.emitCJUMP_Short(x86.JAE, (byte)0);
856             int cloc = asm.getCurrentOffset();
857             asm.emitSHLD_r_r_rc(EDX, EAX);
858             asm.emit2_Reg(x86.SHL_r32_rc, EAX);
859             asm.emitJUMP_Short(x86.JMP, (byte)0);
860             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
861             cloc = asm.getCurrentOffset();
862             asm.emit2_Reg_Reg(x86.MOV_r_r32, EDX, EAX);
863             asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EAX);
864             asm.emit2_Reg(x86.SHL_r32_rc, EDX);
865             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
866         } else if (op instanceof Binary.SHR_L) {
867             asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
868             asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
869             asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
870             asm.emitCJUMP_Short(x86.JAE, (byte)0);
871             int cloc = asm.getCurrentOffset();
872             asm.emitSHRD_r_r_rc(EAX, EDX);
873             asm.emit2_Reg(x86.SAR_r32_rc, EDX);
874             asm.emitJUMP_Short(x86.JMP, (byte)0);
875             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
876             cloc = asm.getCurrentOffset();
877             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDX);
878             asm.emit2_SHIFT_Reg_Imm8(x86.SAR_r32_i, EDX, (byte)31);
879             asm.emit2_Reg(x86.SAR_r32_rc, EAX);
880             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
881         } else if (op instanceof Binary.USHR_L) {
882             asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
883             asm.emitARITH_Reg_Imm(x86.AND_r_i32, ECX, 63);
884             asm.emitARITH_Reg_Imm(x86.CMP_r_i32, ECX, 32);
885             asm.emitCJUMP_Short(x86.JAE, (byte)0);
886             int cloc = asm.getCurrentOffset();
887             asm.emitSHRD_r_r_rc(EAX, EDX);
888             asm.emit2_Reg(x86.SHR_r32_rc, EDX);
889             asm.emitJUMP_Short(x86.JMP, (byte)0);
890             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
891             cloc = asm.getCurrentOffset();
892             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EDX);
893             asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EDX, EDX);
894             asm.emit2_Reg(x86.SHR_r32_rc, EAX);
895             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
896         } else if (op instanceof Binary.CMP_L) {
897             asm.emitARITH_Reg_Reg(x86.SUB_r_r32, EAX, EBX);
898             asm.emitARITH_Reg_Reg(x86.SBB_r_r32, EDX, ECX);
899             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
900             asm.emitCJUMP_Short(x86.JL, (byte)0);
901             int cloc1 = asm.getCurrentOffset();
902             asm.emitARITH_Reg_Reg(x86.XOR_r_r32, ECX, ECX);
903             asm.emitARITH_Reg_Reg(x86.OR_r_r32, EAX, EDX);
904             asm.emitCJUMP_Short(x86.JE, (byte)0);
905             int cloc2 = asm.getCurrentOffset();
906             asm.emitShort_Reg(x86.INC_r32, ECX);
907             asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
908             asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
909             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
910         } else if (op instanceof Binary.CMP_FL) {
911             asm.emitShort_Reg(x86.PUSH_r, EAX);
912             asm.emitShort_Reg(x86.PUSH_r, EBX);
913             asm.emit2_Mem(x86.FLD_m32, 0, ESP);
914             asm.emit2_Mem(x86.FLD_m32, 4, ESP);
915             asm.emit2(x86.FUCOMPP);
916             asm.emit2(x86.FNSTSW_ax);
917             asm.emit1(x86.SAHF);
918             asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
919             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
920             asm.emitCJUMP_Short(x86.JB, (byte)0);
921             int cloc1 = asm.getCurrentOffset();
922             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
923             asm.emitCJUMP_Short(x86.JE, (byte)0);
924             int cloc2 = asm.getCurrentOffset();
925             asm.emitShort_Reg(x86.INC_r32, ECX);
926             asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
927             asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
928             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
929         } else if (op instanceof Binary.CMP_FG) {
930             asm.emitShort_Reg(x86.PUSH_r, EAX);
931             asm.emitShort_Reg(x86.PUSH_r, EBX);
932             asm.emit2_Mem(x86.FLD_m32, 4, ESP); // reverse order
933             asm.emit2_Mem(x86.FLD_m32, 0, ESP);
934             asm.emit2(x86.FUCOMPP);
935             asm.emit2(x86.FNSTSW_ax);
936             asm.emit1(x86.SAHF);
937             asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
938             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 1);
939             asm.emitCJUMP_Short(x86.JB, (byte)0);
940             int cloc1 = asm.getCurrentOffset();
941             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
942             asm.emitCJUMP_Short(x86.JE, (byte)0);
943             int cloc2 = asm.getCurrentOffset();
944             asm.emitShort_Reg(x86.DEC_r32, ECX);
945             asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
946             asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
947             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
948         } else if (op instanceof Binary.CMP_DL) {
949             asm.emitShort_Reg(x86.PUSH_r, EDX);
950             asm.emitShort_Reg(x86.PUSH_r, EAX);
951             asm.emitShort_Reg(x86.PUSH_r, ECX);
952             asm.emitShort_Reg(x86.PUSH_r, EBX);
953             asm.emit2_Mem(x86.FLD_m64, 0, ESP);
954             asm.emit2_Mem(x86.FLD_m64, 8, ESP);
955             asm.emit2(x86.FUCOMPP);
956             asm.emit2(x86.FNSTSW_ax);
957             asm.emit1(x86.SAHF);
958             asm.emit2_Reg_Mem(x86.LEA, ESP, 16, ESP);
959             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, -1);
960             asm.emitCJUMP_Short(x86.JB, (byte)0);
961             int cloc1 = asm.getCurrentOffset();
962             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
963             asm.emitCJUMP_Short(x86.JE, (byte)0);
964             int cloc2 = asm.getCurrentOffset();
965             asm.emitShort_Reg(x86.INC_r32, ECX);
966             asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
967             asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
968             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
969         } else if (op instanceof Binary.CMP_DG) {
970             asm.emitShort_Reg(x86.PUSH_r, EDX);
971             asm.emitShort_Reg(x86.PUSH_r, EAX);
972             asm.emitShort_Reg(x86.PUSH_r, ECX);
973             asm.emitShort_Reg(x86.PUSH_r, EBX);
974             asm.emit2_Mem(x86.FLD_m64, 8, ESP); // reverse order
975             asm.emit2_Mem(x86.FLD_m64, 0, ESP);
976             asm.emit2(x86.FUCOMPP);
977             asm.emit2(x86.FNSTSW_ax);
978             asm.emit1(x86.SAHF);
979             asm.emit2_Reg_Mem(x86.LEA, ESP, 16, ESP);
980             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 1);
981             asm.emitCJUMP_Short(x86.JB, (byte)0);
982             int cloc1 = asm.getCurrentOffset();
983             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
984             asm.emitCJUMP_Short(x86.JE, (byte)0);
985             int cloc2 = asm.getCurrentOffset();
986             asm.emitShort_Reg(x86.DEC_r32, ECX);
987             asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
988             asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
989             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
990         } else if (op instanceof Binary.ALIGN_P) {
991             asm.emit2_Reg_Reg(x86.MOV_r_r32, ECX, EBX);
992             asm.emitShort_Reg_Imm(x86.MOV_r_i32, EBX, 1);
993             asm.emit2_Reg(x86.SHL_r32_rc, EBX);
994             asm.emitShort_Reg(x86.DEC_r32, EBX);
995             asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, EBX);
996             asm.emit2_Reg(x86.NOT_r32, EBX);
997             asm.emitARITH_Reg_Reg(x86.AND_r_r32, EAX, EBX);
998         }
999         else {
1000             Assert.UNREACHABLE(obj.toString());
1001         }
1002         storeOperand(Binary.getDest(obj), EAX);
1003         this.handled = true;
1004     }
1005     /***
1006      * @see joeq.Compiler.Quad.QuadVisitor#visitBoundsCheck(joeq.Compiler.Quad.Quad)
1007      */
1008     public void visitBoundsCheck(Quad obj) {
1009         if (TRACE) System.out.println(this+" BoundsCheck: "+obj);
1010         loadOperand(BoundsCheck.getRef(obj), EAX);
1011         loadOperand(BoundsCheck.getIndex(obj), EBX);
1012         asm.emitARITH_Reg_Mem(x86.CMP_r_m32, EBX, ObjectLayout.ARRAY_LENGTH_OFFSET, EAX);
1013         asm.emitCJUMP_Short(x86.JB, (byte)2); asm.emit1_Imm8(x86.INT_i8, BOUNDS_EX_NUM);
1014         this.handled = true;
1015     }
1016     /***
1017      * @see joeq.Compiler.Quad.QuadVisitor#visitCheckCast(joeq.Compiler.Quad.Quad)
1018      */
1019     public void visitCheckCast(Quad obj) {
1020         if (TRACE) System.out.println(this+" CheckCast: "+obj);
1021         loadOperand(CheckCast.getSrc(obj), EAX);
1022         asm.emitShort_Reg(x86.PUSH_r, EAX);
1023         jq_Type f = CheckCast.getType(obj).getType();
1024         emitPushAddressOf(f);
1025         emitCallRelative(TypeCheck._checkcast);
1026         storeOperand(CheckCast.getDest(obj), EAX);
1027         this.handled = true;
1028     }
1029     /***
1030      * @see joeq.Compiler.Quad.QuadVisitor#visitGetfield(joeq.Compiler.Quad.Quad)
1031      */
1032     public void visitGetfield(Quad obj) {
1033         if (TRACE) System.out.println(this+" Getfield: "+obj);
1034         jq_InstanceField f = (jq_InstanceField) Getfield.getField(obj).getField();
1035         loadOperand(Getfield.getBase(obj), EAX);
1036         asm.emitShort_Reg(x86.PUSH_r, EAX);
1037         if (f.getWidth() == 1) {
1038             if (f.needsDynamicLink(method)) {
1039                 // generate a runtime call, which will be backpatched.
1040                 asm.startDynamicPatch(10); // 9
1041                 emitPushAddressOf(f);
1042                 emitCallRelative(x86ReferenceLinker._getfield1);
1043                 asm.endDynamicPatch();
1044             } else {
1045                 asm.emitShort_Reg(x86.POP_r, EAX); // obj ref
1046                 asm.emit3_Reg_Mem(x86.MOVSX_r_m8, EBX, f.getOffset(), EAX);
1047                 asm.emitShort_Reg(x86.PUSH_r, EBX);
1048             }
1049             asm.emitShort_Reg(x86.POP_r, EAX);
1050         } else if (f.getWidth() == 4) {
1051             if (f.needsDynamicLink(method)) {
1052                 // generate a runtime call, which will be backpatched.
1053                 asm.startDynamicPatch(10); // 7
1054                 emitPushAddressOf(f);
1055                 emitCallRelative(x86ReferenceLinker._getfield4);
1056                 asm.endDynamicPatch();
1057             } else {
1058                 asm.emitShort_Reg(x86.POP_r, EAX); // obj ref
1059                 asm.emit2_Mem(x86.PUSH_m, f.getOffset(), EAX);
1060             }
1061             asm.emitShort_Reg(x86.POP_r, EAX);
1062         } else if (f.getWidth() == 8) {
1063             if (f.needsDynamicLink(method)) {
1064                 // generate a runtime call, which will be backpatched.
1065                 asm.startDynamicPatch(13);
1066                 emitPushAddressOf(f);
1067                 emitCallRelative(x86ReferenceLinker._getfield8);
1068                 asm.endDynamicPatch();
1069             } else {
1070                 asm.emitShort_Reg(x86.POP_r, EAX); // obj ref
1071                 asm.emit2_Mem(x86.PUSH_m, f.getOffset()+4, EAX); // hi
1072                 asm.emit2_Mem(x86.PUSH_m, f.getOffset(), EAX);   // lo
1073             }
1074             asm.emitShort_Reg(x86.POP_r, EAX);
1075             asm.emitShort_Reg(x86.POP_r, EDX);
1076         } else if (f.getType() == jq_Primitive.SHORT) {
1077             if (f.needsDynamicLink(method)) {
1078                 // generate a runtime call, which will be backpatched.
1079                 asm.startDynamicPatch(10); // 9
1080                 emitPushAddressOf(f);
1081                 emitCallRelative(x86ReferenceLinker._sgetfield);
1082                 asm.endDynamicPatch();
1083             } else {
1084                 asm.emitShort_Reg(x86.POP_r, EAX); // obj ref
1085                 asm.emit3_Reg_Mem(x86.MOVSX_r_m16, EBX, f.getOffset(), EAX);
1086                 asm.emitShort_Reg(x86.PUSH_r, EBX);
1087             }
1088             asm.emitShort_Reg(x86.POP_r, EAX);
1089         } else if (f.getType() == jq_Primitive.CHAR) {
1090             if (f.needsDynamicLink(method)) {
1091                 // generate a runtime call, which will be backpatched.
1092                 asm.startDynamicPatch(10); // 9
1093                 emitPushAddressOf(f);
1094                 emitCallRelative(x86ReferenceLinker._cgetfield);
1095                 asm.endDynamicPatch();
1096             } else {
1097                 asm.emitShort_Reg(x86.POP_r, EAX); // obj ref
1098                 asm.emit3_Reg_Mem(x86.MOVZX_r_m16, EBX, f.getOffset(), EAX);
1099                 asm.emitShort_Reg(x86.PUSH_r, EBX);
1100             }
1101             asm.emitShort_Reg(x86.POP_r, EAX);
1102         }
1103         else {
1104             Assert.UNREACHABLE();
1105         }
1106         storeOperand(Getfield.getDest(obj), EAX);
1107         this.handled = true;
1108     }
1109     /***
1110      * @see joeq.Compiler.Quad.QuadVisitor#visitGetstatic(joeq.Compiler.Quad.Quad)
1111      */
1112     public void visitGetstatic(Quad obj) {
1113         if (TRACE) System.out.println(this+" Getstatic: "+obj);
1114         jq_StaticField f = (jq_StaticField) Getstatic.getField(obj).getField();
1115         if (f.getWidth() == 8) {
1116             if (f.needsDynamicLink(method)) {
1117                 // generate a runtime call, which will be backpatched.
1118                 asm.startDynamicPatch(12); // 6
1119                 emitPushAddressOf(f);
1120                 emitCallRelative(x86ReferenceLinker._getstatic8);
1121                 asm.endDynamicPatch();
1122             } else {
1123                 emitPushMemory(f);
1124             }
1125             asm.emitShort_Reg(x86.POP_r, EAX);
1126             asm.emitShort_Reg(x86.POP_r, EDX);
1127         } else {
1128             if (f.needsDynamicLink(method)) {
1129                 // generate a runtime call, which will be backpatched.
1130                 asm.startDynamicPatch(10); // 6
1131                 emitPushAddressOf(f);
1132                 emitCallRelative(x86ReferenceLinker._getstatic4);
1133                 asm.endDynamicPatch();
1134             } else {
1135                 emitPushMemory(f);
1136             }
1137             asm.emitShort_Reg(x86.POP_r, EAX);
1138         }
1139         storeOperand(Getstatic.getDest(obj), EAX);
1140         this.handled = true;
1141     }
1142     /***
1143      * @see joeq.Compiler.Quad.QuadVisitor#visitGoto(joeq.Compiler.Quad.Quad)
1144      */
1145     public void visitGoto(Quad obj) {
1146         if (TRACE) System.out.println(this+" Goto: "+obj);
1147         branchHelper(BytecodeVisitor.CMP_UNCOND, Goto.getTarget(obj).getTarget());
1148         this.handled = true;
1149     }
1150     private void branchHelper(byte op, BasicBlock target) {
1151         if (op == BytecodeVisitor.CMP_UNCOND) {
1152             if (asm.containsTarget(target))
1153                 asm.emitJUMP_Back(x86.JMP, target);
1154             else
1155                 asm.emitJUMP_Forw(x86.JMP, target);
1156         } else {
1157             x86 opc = null;
1158             switch(op) {
1159                 case BytecodeVisitor.CMP_EQ: opc = x86.JE; break;
1160                 case BytecodeVisitor.CMP_NE: opc = x86.JNE; break;
1161                 case BytecodeVisitor.CMP_LT: opc = x86.JL; break;
1162                 case BytecodeVisitor.CMP_GE: opc = x86.JGE; break;
1163                 case BytecodeVisitor.CMP_LE: opc = x86.JLE; break;
1164                 case BytecodeVisitor.CMP_GT: opc = x86.JG; break;
1165                 case BytecodeVisitor.CMP_AE: opc = x86.JAE; break;
1166                 default: Assert.UNREACHABLE();
1167             }
1168             if (asm.containsTarget(target))
1169                 asm.emitCJUMP_Back(opc, target);
1170             else
1171                 asm.emitCJUMP_Forw(opc, target);
1172         }
1173         this.handled = true;
1174     }
1175     /***
1176      * @see joeq.Compiler.Quad.QuadVisitor#visitInstanceOf(joeq.Compiler.Quad.Quad)
1177      */
1178     public void visitInstanceOf(Quad obj) {
1179         if (TRACE) System.out.println(this+" InstanceOf: "+obj);
1180         loadOperand(InstanceOf.getSrc(obj), EAX);
1181         asm.emitShort_Reg(x86.PUSH_r, EAX);
1182         jq_Type f = InstanceOf.getType(obj).getType();
1183         emitPushAddressOf(f);
1184         emitCallRelative(TypeCheck._instance_of);
1185         storeOperand(InstanceOf.getDest(obj), EAX);
1186         this.handled = true;
1187     }
1188     /***
1189      * @see joeq.Compiler.Quad.QuadVisitor#visitIntIfCmp(joeq.Compiler.Quad.Quad)
1190      */
1191     public void visitIntIfCmp(Quad obj) {
1192         if (TRACE) System.out.println(this+" IntIfCmp: "+obj);
1193         loadOperand(IntIfCmp.getSrc1(obj), EAX);
1194         loadOperand(IntIfCmp.getSrc2(obj), ECX);
1195         asm.emitARITH_Reg_Reg(x86.CMP_r_r32, EAX, ECX);
1196         branchHelper(IntIfCmp.getCond(obj).getCondition(), IntIfCmp.getTarget(obj).getTarget());
1197         this.handled = true;
1198     }
1199     private void INVOKEDPATCHhelper(byte op, jq_Method f) {
1200         int dpatchsize;
1201         jq_StaticMethod dpatchentry;
1202         switch (op) {
1203             case BytecodeVisitor.INVOKE_VIRTUAL:
1204                 dpatchsize = 16;
1205                 dpatchentry = x86ReferenceLinker._invokevirtual;
1206                 break;
1207             case BytecodeVisitor.INVOKE_STATIC:
1208                 dpatchsize = 11; // 5
1209                 dpatchentry = x86ReferenceLinker._invokestatic;
1210                 break;
1211             case BytecodeVisitor.INVOKE_SPECIAL:
1212                 dpatchsize = 11; // 5
1213                 dpatchentry = x86ReferenceLinker._invokespecial;
1214                 break;
1215             case BytecodeVisitor.INVOKE_INTERFACE:
1216                 // fallthrough
1217             default:
1218                 throw new InternalError();
1219         }
1220         // generate a runtime call, which will be backpatched.
1221         asm.startDynamicPatch(dpatchsize);
1222         emitPushAddressOf(f);
1223         emitCallRelative(dpatchentry);
1224         asm.endDynamicPatch();
1225         this.handled = true;
1226     }
1227     private void INVOKENODPATCHhelper(byte op, jq_Method f) {
1228         switch(op) {
1229             case BytecodeVisitor.INVOKE_VIRTUAL: {
1230                 int objptroffset = (f.getParamWords() << 2) - 4;
1231                 int m_off = ((jq_InstanceMethod)f).getOffset();
1232                 asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, objptroffset, ESP); // 7
1233                 asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, ObjectLayout.VTABLE_OFFSET, EAX); // 3
1234                 asm.emit2_Mem(x86.CALL_m, m_off, EBX); // 6
1235                 break;
1236             }
1237             case BytecodeVisitor.INVOKE_SPECIAL:
1238                 f = jq_Class.getInvokespecialTarget(method.getDeclaringClass(), (jq_InstanceMethod)f);
1239                 emitCallRelative(f);
1240                 break;
1241             case BytecodeVisitor.INVOKE_STATIC:
1242                 emitCallRelative(f);
1243                 break;
1244             case BytecodeVisitor.INVOKE_INTERFACE:
1245                 //jq.Assert(!jq.RunningNative || f.getDeclaringClass().isInterface());
1246                 emitPushAddressOf(f);
1247                 emitCallRelative(x86ReferenceLinker._invokeinterface);
1248                 // need to pop args ourselves.
1249                 asm.emit2_Reg_Mem(x86.LEA, ESP, f.getParamWords()<<2, ESP);
1250                 break;
1251             default:
1252                 Assert.UNREACHABLE();
1253         }
1254         this.handled = true;
1255     }
1256     private void INVOKEhelper(byte op, jq_Method f) {
1257         switch (op) {
1258             case BytecodeVisitor.INVOKE_VIRTUAL:
1259                 if (f.needsDynamicLink(method))
1260                     INVOKEDPATCHhelper(op, f);
1261                 else
1262                     INVOKENODPATCHhelper(op, f);
1263                 break;
1264             case BytecodeVisitor.INVOKE_STATIC:
1265                 // fallthrough
1266             case BytecodeVisitor.INVOKE_SPECIAL:
1267                 if (f.needsDynamicLink(method))
1268                     INVOKEDPATCHhelper(op, f);
1269                 else
1270                     INVOKENODPATCHhelper(op, f);
1271                 break;
1272             case BytecodeVisitor.INVOKE_INTERFACE:
1273                 INVOKENODPATCHhelper(op, f);
1274                 break;
1275             default:
1276                 throw new InternalError();
1277         }
1278         this.handled = true;
1279     }
1280     /***
1281      * @see joeq.Compiler.Quad.QuadVisitor#visitInvoke(joeq.Compiler.Quad.Quad)
1282      */
1283     public void visitInvoke(Quad obj) {
1284         if (TRACE) System.out.println(this+" Invoke: "+obj);
1285         byte type = ((Invoke)obj.getOperator()).getType();
1286         ParamListOperand plo = Invoke.getParamList(obj);
1287         for (int i=0; i<plo.length(); ++i) {
1288             RegisterOperand r = plo.get(i);
1289             loadOperand(r, EAX);
1290             if (r.getType().getReferenceSize() == 8)
1291                 asm.emitShort_Reg(x86.PUSH_r, EDX);
1292             asm.emitShort_Reg(x86.PUSH_r, EAX);
1293         }
1294         jq_Method f = Invoke.getMethod(obj).getMethod();
1295         INVOKEhelper(type, f);
1296         
1297         // clean up extra pushed arguments for varargs methods like multinewarray.
1298         int diff = plo.words() - f.getParamWords();
1299         if (diff != 0)
1300             asm.emit2_Reg_Mem(x86.LEA, ESP, diff<<2, ESP);
1301         
1302         jq_Type t = ((Invoke)obj.getOperator()).getReturnType();
1303         if (t.getReferenceSize() > 0) {
1304             storeOperand(Invoke.getDest(obj), EAX);
1305         }
1306         this.handled = true;
1307     }
1308     /***
1309      * @see joeq.Compiler.Quad.QuadVisitor#visitJsr(joeq.Compiler.Quad.Quad)
1310      */
1311     public void visitJsr(Quad obj) {
1312         if (TRACE) System.out.println(this+" Jsr: "+obj);
1313         BasicBlock succ = Jsr.getSuccessor(obj).getTarget();
1314         if (asm.containsTarget(succ)) {
1315             int offset = asm.getBranchTarget(succ);
1316             CodeAddress a = (CodeAddress) asm.getStartAddress().offset(offset);
1317             asm.emitShort_Reg_Imm(x86.MOV_r_i32, EAX, a.to32BitValue());
1318             Code2CodeReference r = new Code2CodeReference((CodeAddress) asm.getCurrentAddress().offset(-4), a);
1319             code_relocs.add(r);
1320         } else {
1321             asm.emitShort_Reg_Imm(x86.MOV_r_i32, EAX, 0x77777777);
1322             asm.recordAbsoluteReference(4, succ);
1323             // hack: null references don't actually get written, so this works.
1324             Code2CodeReference r = new Code2CodeReference((CodeAddress) asm.getCurrentAddress().offset(-4), null);
1325             code_relocs.add(r);
1326         }
1327         storeOperand(Jsr.getDest(obj), EAX);
1328         branchHelper(BytecodeVisitor.CMP_UNCOND, Jsr.getTarget(obj).getTarget());
1329         this.handled = true;
1330     }
1331     /***
1332      * @see joeq.Compiler.Quad.QuadVisitor#visitLookupSwitch(joeq.Compiler.Quad.Quad)
1333      */
1334     public void visitLookupSwitch(Quad obj) {
1335         if (TRACE) System.out.println(this+" LookupSwitch: "+obj);
1336         loadOperand(LookupSwitch.getSrc(obj), EAX);
1337         int n = LookupSwitch.getSize(obj);
1338         for (int i=0; i<n; ++i) {
1339             int match = LookupSwitch.getMatch(obj, i);
1340             asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, match);
1341             BasicBlock target = LookupSwitch.getTarget(obj, i);
1342             branchHelper(BytecodeVisitor.CMP_EQ, target);
1343         }
1344         branchHelper(BytecodeVisitor.CMP_UNCOND, LookupSwitch.getDefault(obj).getTarget());
1345         this.handled = true;
1346     }
1347     /***
1348      * @see joeq.Compiler.Quad.QuadVisitor#visitMemLoad(joeq.Compiler.Quad.Quad)
1349      */
1350     public void visitMemLoad(Quad obj) {
1351         if (TRACE) System.out.println(this+" MemLoad: "+obj);
1352         loadOperand(MemLoad.getAddress(obj), EAX);
1353         MemLoad op = (MemLoad) obj.getOperator();
1354         if (op instanceof MemLoad.PEEK_1) {
1355             asm.emit3_Reg_Mem(x86.MOVSX_r_m8, ECX, 0, EAX);
1356         } else if (op instanceof MemLoad.PEEK_2) {
1357             asm.emit3_Reg_Mem(x86.MOVSX_r_m16, ECX, 0, EAX);
1358         } else if (op instanceof MemLoad.PEEK_4) {
1359             asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, 0, EAX);
1360         } else if (op instanceof MemLoad.PEEK_8) {
1361             asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, 0, EAX);
1362             asm.emit2_Reg_Mem(x86.MOV_r_m32, EBX, 4, EAX);
1363         } else if (op instanceof MemLoad.PEEK_P) {
1364             asm.emit2_Reg_Mem(x86.MOV_r_m32, ECX, 0, EAX);
1365         }
1366         else {
1367             Assert.UNREACHABLE(obj.toString());
1368         }
1369         storeOperand(MemLoad.getDest(obj), ECX);
1370         this.handled = true;
1371     }
1372     /***
1373      * @see joeq.Compiler.Quad.QuadVisitor#visitMemStore(joeq.Compiler.Quad.Quad)
1374      */
1375     public void visitMemStore(Quad obj) {
1376         if (TRACE) System.out.println(this+" MemStore: "+obj);
1377         loadOperand(MemStore.getAddress(obj), EAX);
1378         loadOperand(MemStore.getValue(obj), EBX);
1379         MemStore op = (MemStore) obj.getOperator();
1380         if (op instanceof MemStore.POKE_1) {
1381             asm.emit2_Reg_Mem(x86.MOV_m_r8, EBX, 0, EAX);
1382         } else if (op instanceof MemStore.POKE_2) {
1383             asm.emitprefix(x86.PREFIX_16BIT);
1384             asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
1385         } else if (op instanceof MemStore.POKE_4) {
1386             asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
1387         } else if (op instanceof MemStore.POKE_8) {
1388             asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
1389             asm.emit2_Reg_Mem(x86.MOV_m_r32, ECX, 4, EAX);
1390         } else if (op instanceof MemStore.POKE_P) {
1391             asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, 0, EAX);
1392         }
1393         else {
1394             Assert.UNREACHABLE(obj.toString());
1395         }
1396         this.handled = true;
1397     }
1398     /***
1399      * @see joeq.Compiler.Quad.QuadVisitor#visitMonitor(joeq.Compiler.Quad.Quad)
1400      */
1401     public void visitMonitor(Quad obj) {
1402         if (TRACE) System.out.println(this+" Monitor: "+obj);
1403         loadOperand(Monitor.getSrc(obj), EAX);
1404         asm.emitShort_Reg(x86.PUSH_r, EAX);
1405         jq_StaticMethod m = (obj.getOperator() instanceof Monitor.MONITORENTER)?joeq.Runtime.Monitor._monitorenter:joeq.Runtime.Monitor._monitorexit;
1406         emitCallRelative(m);
1407         this.handled = true;
1408     }
1409     /***
1410      * @see joeq.Compiler.Quad.QuadVisitor#visitMove(joeq.Compiler.Quad.Quad)
1411      */
1412     public void visitMove(Quad obj) {
1413         if (TRACE) System.out.println(this+" Move: "+obj);
1414         //Move o = (Move) obj.getOperator();
1415         RegisterOperand dest_o = Move.getDest(obj);
1416         Operand src_o = Move.getSrc(obj);
1417         loadOperand(src_o, EAX);
1418         storeOperand(dest_o, EAX);
1419         this.handled = true;
1420     }
1421     /***
1422      * @see joeq.Compiler.Quad.QuadVisitor#visitPhi(joeq.Compiler.Quad.Quad)
1423      */
1424     public void visitPhi(Quad obj) {
1425         if (TRACE) System.out.println(this+" Phi: "+obj);
1426         Assert.UNREACHABLE();
1427     }
1428     /***
1429      * @see joeq.Compiler.Quad.QuadVisitor#visitNew(joeq.Compiler.Quad.Quad)
1430      */
1431     public void visitNew(Quad obj) {
1432         if (TRACE) System.out.println(this+" New: "+obj);
1433         jq_Type f = New.getType(obj).getType();
1434         if (f.isClassType() && !f.needsDynamicLink(method)) {
1435             jq_Class k = (jq_Class)f;
1436             asm.emitPUSH_i(k.getInstanceSize());
1437             emitPushAddressOf(k.getVTable());
1438             emitCallRelative(DefaultHeapAllocator._allocateObject);
1439         } else {
1440             emitPushAddressOf(f);
1441             emitCallRelative(HeapAllocator._clsinitAndAllocateObject);
1442         }
1443         storeOperand(New.getDest(obj), EAX);
1444         this.handled = true;
1445     }
1446     /***
1447      * @see joeq.Compiler.Quad.QuadVisitor#visitNewArray(joeq.Compiler.Quad.Quad)
1448      */
1449     public void visitNewArray(Quad obj) {
1450         if (TRACE) System.out.println(this+" NewArray: "+obj);
1451         jq_Array f = (jq_Array) NewArray.getType(obj).getType();
1452         // initialize type now, to avoid backpatch.
1453         if (!jq.RunningNative) {
1454             //jq.Assert(jq.boot_types.contains(f), f.toString());
1455         } else {
1456             f.cls_initialize();
1457         }
1458         byte width = f.getLogElementSize();
1459         loadOperand(NewArray.getSize(obj), EAX);
1460         asm.emitShort_Reg(x86.PUSH_r, EAX);
1461         asm.emitShort_Reg(x86.PUSH_r, EAX);
1462         if (width != 0) asm.emit2_SHIFT_Mem_Imm8(x86.SHL_m32_i, 0, ESP, width);
1463         asm.emitARITH_Mem_Imm(x86.ADD_m_i32, 0, ESP, ObjectLayout.ARRAY_HEADER_SIZE);
1464         emitPushAddressOf(f.getVTable());
1465         emitCallRelative(DefaultHeapAllocator._allocateArray);
1466         storeOperand(NewArray.getDest(obj), EAX);
1467         this.handled = true;
1468     }
1469     /***
1470      * @see joeq.Compiler.Quad.QuadVisitor#visitNullCheck(joeq.Compiler.Quad.Quad)
1471      */
1472     public void visitNullCheck(Quad obj) {
1473         if (TRACE) System.out.println(this+" NullCheck: "+obj);
1474         loadOperand(NullCheck.getSrc(obj), EAX);
1475         asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, 0, EAX);
1476         this.handled = true;
1477     }
1478     /***
1479      * @see joeq.Compiler.Quad.QuadVisitor#visitPutfield(joeq.Compiler.Quad.Quad)
1480      */
1481     public void visitPutfield(Quad obj) {
1482         if (TRACE) System.out.println(this+" Putfield: "+obj);
1483         jq_InstanceField f = (jq_InstanceField) Putfield.getField(obj).getField();
1484         loadOperand(Putfield.getBase(obj), EAX);
1485         asm.emitShort_Reg(x86.PUSH_r, EAX);
1486         loadOperand(Putfield.getSrc(obj), EAX);
1487         if (f.getWidth() == 8)
1488             asm.emitShort_Reg(x86.PUSH_r, EDX);
1489         asm.emitShort_Reg(x86.PUSH_r, EAX);
1490         if (f.getWidth() == 1) {
1491             if (f.needsDynamicLink(method)) {
1492                 // generate a runtime call, which will be backpatched.
1493                 asm.startDynamicPatch(10); // 8
1494                 emitPushAddressOf(f);
1495                 emitCallRelative(x86ReferenceLinker._putfield1);
1496                 asm.endDynamicPatch();
1497             } else {
1498                 // field has already been resolved.
1499                 asm.emitShort_Reg(x86.POP_r, EBX);
1500                 asm.emitShort_Reg(x86.POP_r, EAX);
1501                 asm.emit2_Reg_Mem(x86.MOV_m_r8, EBX, f.getOffset(), EAX);
1502             }
1503         } else if (f.getWidth() == 4) {
1504             if (f.needsDynamicLink(method)) {
1505                 // generate a runtime call, which will be backpatched.
1506                 asm.startDynamicPatch(10); // 8
1507                 emitPushAddressOf(f);
1508                 emitCallRelative(x86ReferenceLinker._putfield4);
1509                 asm.endDynamicPatch();
1510             } else {
1511                 // field has already been resolved.
1512                 asm.emitShort_Reg(x86.POP_r, EBX);
1513                 asm.emitShort_Reg(x86.POP_r, EAX);
1514                 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset(), EAX);
1515             }
1516         } else if (f.getWidth() == 8) {
1517             if (f.needsDynamicLink(method)) {
1518                 // generate a runtime call, which will be backpatched.
1519                 asm.startDynamicPatch(15);
1520                 emitPushAddressOf(f);
1521                 emitCallRelative(x86ReferenceLinker._putfield8);
1522                 asm.endDynamicPatch();
1523             } else {
1524                 // field has already been resolved.
1525                 asm.emitShort_Reg(x86.POP_r, EBX); // lo
1526                 asm.emitShort_Reg(x86.POP_r, EAX); // hi
1527                 asm.emitShort_Reg(x86.POP_r, EDX);
1528                 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset()  , EDX); // lo
1529                 asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, f.getOffset()+4, EDX); // hi
1530             }
1531         } else if (f.getWidth() == 2) {
1532             if (f.needsDynamicLink(method)) {
1533                 // generate a runtime call, which will be backpatched.
1534                 asm.startDynamicPatch(10); // 9
1535                 emitPushAddressOf(f);
1536                 emitCallRelative(x86ReferenceLinker._putfield2);
1537                 asm.endDynamicPatch();
1538             } else {
1539                 // field has already been resolved.
1540                 asm.emitShort_Reg(x86.POP_r, EBX);
1541                 asm.emitShort_Reg(x86.POP_r, EAX);
1542                 asm.emitprefix(x86.PREFIX_16BIT);
1543                 asm.emit2_Reg_Mem(x86.MOV_m_r32, EBX, f.getOffset(), EAX);
1544             }
1545         }
1546         else {
1547             Assert.UNREACHABLE(obj.toString());
1548         }
1549         this.handled = true;
1550     }
1551     /***
1552      * @see joeq.Compiler.Quad.QuadVisitor#visitPutstatic(joeq.Compiler.Quad.Quad)
1553      */
1554     public void visitPutstatic(Quad obj) {
1555         if (TRACE) System.out.println(this+" Putstatic: "+obj);
1556         jq_StaticField f = (jq_StaticField) Putstatic.getField(obj).getField();
1557         loadOperand(Putstatic.getSrc(obj), EAX);
1558         if (f.getWidth() == 8) {
1559             asm.emitShort_Reg(x86.PUSH_r, EDX);
1560             asm.emitShort_Reg(x86.PUSH_r, EAX);
1561             if (f.needsDynamicLink(method)) {
1562                 // generate a runtime call, which will be backpatched.
1563                 asm.startDynamicPatch(12);
1564                 emitPushAddressOf(f);
1565                 emitCallRelative(x86ReferenceLinker._putstatic8);
1566                 asm.endDynamicPatch();
1567             } else {
1568                 emitPopMemory8(f);
1569             }
1570         } else {
1571             asm.emitShort_Reg(x86.PUSH_r, EAX);
1572             if (f.needsDynamicLink(method)) {
1573                 // generate a runtime call, which will be backpatched.
1574                 asm.startDynamicPatch(10); // 6
1575                 emitPushAddressOf(f);
1576                 emitCallRelative(x86ReferenceLinker._putstatic4);
1577                 asm.endDynamicPatch();
1578             } else {
1579                 emitPopMemory(f);
1580             }
1581         }
1582         this.handled = true;
1583     }
1584     /***
1585      * @see joeq.Compiler.Quad.QuadVisitor#visitRet(joeq.Compiler.Quad.Quad)
1586      */
1587     public void visitRet(Quad obj) {
1588         if (TRACE) System.out.println(this+" Ret: "+obj);
1589         asm.emit2_Mem(x86.JMP_m, getStackOffset(Ret.getTarget(obj)), EBP);
1590         this.handled = true;
1591     }
1592     /***
1593      * @see joeq.Compiler.Quad.QuadVisitor#visitReturn(joeq.Compiler.Quad.Quad)
1594      */
1595     public void visitReturn(Quad obj) {
1596         if (TRACE) System.out.println(this+" Return: "+obj);
1597         Return o = (Return)obj.getOperator();
1598         if (o instanceof Return.THROW_A) {
1599             loadOperand(Return.getSrc(obj), EAX);
1600             asm.emitShort_Reg(x86.PUSH_r, EAX);
1601             emitCallRelative(ExceptionDeliverer._athrow);
1602         }
1603         if (method.isSynchronized()) SYNCHEXIThelper();
1604         if (TraceMethods) {
1605             emitPushAddressOf(SystemInterface.toCString("Leaving: "+method));
1606             emitCallMemory(SystemInterface._debugwriteln);
1607         }
1608         if (!(o instanceof Return.RETURN_V)) {
1609             loadOperand(Return.getSrc(obj), EAX);
1610         }
1611         // epilogue
1612         asm.emit1(x86.LEAVE);              // esp<-ebp, pop ebp
1613         asm.emit1_Imm16(x86.RET_i, (char)(n_paramwords<<2));
1614         this.handled = true;
1615     }
1616     private void SYNCHEXIThelper() {
1617         if (method.isStatic()) {
1618             if (TraceQuads) {
1619                 emitPushAddressOf(SystemInterface.toCString("exit: STATIC SYNCH EXIT"));
1620                 emitCallMemory(SystemInterface._debugwriteln);
1621             }
1622             // lock the java.lang.Class object
1623             Class c = Reflection.getJDKType(method.getDeclaringClass());
1624             Assert._assert(c != null);
1625             emitPushAddressOf(c);
1626         } else {
1627             if (TraceQuads) {
1628                 emitPushAddressOf(SystemInterface.toCString("exit: INSTANCE SYNCH EXIT"));
1629                 emitCallMemory(SystemInterface._debugwriteln);
1630             }
1631             // lock the this pointer
1632             asm.emit2_Mem(x86.PUSH_m, getParamOffset(0), EBP);
1633         }
1634         emitCallRelative(joeq.Runtime.Monitor._monitorexit);
1635         this.handled = true;
1636     }
1637     /***
1638      * @see joeq.Compiler.Quad.QuadVisitor#visitSpecial(joeq.Compiler.Quad.Quad)
1639      */
1640     public void visitSpecial(Quad obj) {
1641         if (TRACE) System.out.println(this+" Special: "+obj);
1642         Special o = (Special) obj.getOperator();
1643         if (o instanceof Special.GET_EXCEPTION) {
1644             // already done.
1645         } else if (o instanceof Special.GET_BASE_POINTER) {
1646             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, EBP);
1647             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1648         } else if (o instanceof Special.GET_STACK_POINTER) {
1649             asm.emitShort_Reg(x86.PUSH_r, ESP);
1650             asm.emitShort_Reg(x86.POP_r, EAX);
1651             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1652         } else if (o instanceof Special.GET_THREAD_BLOCK) {
1653             asm.emitprefix(THREAD_BLOCK_PREFIX);
1654             asm.emit2_Reg_Mem(x86.MOV_r_m32, EAX, THREAD_BLOCK_OFFSET);
1655             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1656         } else if (o instanceof Special.SET_THREAD_BLOCK) {
1657             loadOperand(Special.getOp2(obj), EAX);
1658             asm.emitprefix(THREAD_BLOCK_PREFIX);
1659             asm.emit2_Reg_Mem(x86.MOV_m_r32, EAX, THREAD_BLOCK_OFFSET);
1660         } else if (o instanceof Special.ALLOCA) {
1661             loadOperand(Special.getOp2(obj), EAX);
1662             asm.emit2_Reg(x86.NEG_r32, EAX);
1663             asm.emitARITH_Reg_Reg(x86.ADD_r_r32, EAX, ESP);
1664             asm.emit2_Reg_Reg(x86.MOV_r_r32, ESP, EAX);
1665             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1666         } else if (o instanceof Special.ATOMICADD_I) {
1667             loadOperand(Special.getOp2(obj), EAX);
1668             loadOperand(Special.getOp3(obj), EBX);
1669             if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1670             asm.emitARITH_Reg_Mem(x86.ADD_m_r32, EBX, 0, EAX);
1671         } else if (o instanceof Special.ATOMICSUB_I) {
1672             loadOperand(Special.getOp2(obj), EAX);
1673             loadOperand(Special.getOp3(obj), EBX);
1674             if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1675             asm.emitARITH_Reg_Mem(x86.SUB_m_r32, EBX, 0, EAX);
1676         } else if (o instanceof Special.ATOMICAND_I) {
1677             loadOperand(Special.getOp2(obj), EAX);
1678             loadOperand(Special.getOp3(obj), EBX);
1679             if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1680             asm.emitARITH_Reg_Mem(x86.AND_m_r32, EBX, 0, EAX);
1681         } else if (o instanceof Special.ATOMICCAS4) {
1682             loadOperand(Special.getOp2(obj), ECX);
1683             loadOperand(Special.getOp3(obj), EAX);
1684             loadOperand(Special.getOp4(obj), EBX);
1685             if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1686             asm.emit3_Reg_Mem(x86.CMPXCHG_32, EBX, 0, ECX);
1687             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1688         } else if (o instanceof Special.ATOMICCAS8) {
1689             // untested.
1690             loadOperand(Special.getOp2(obj), EDI);
1691             loadOperand(Special.getOp3(obj), EAX);
1692             loadOperand(Special.getOp4(obj), EDI);
1693             if (jq.SMP) asm.emitprefix(x86.PREFIX_LOCK);
1694             asm.emit3_Reg_Mem(x86.CMPXCHG8B, EAX, 0, EDI);
1695             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1696         } else if (o instanceof Special.LONG_JUMP) {
1697             loadOperand(Special.getOp1(obj), ECX);
1698             loadOperand(Special.getOp3(obj), EBX);
1699             loadOperand(Special.getOp4(obj), EAX);
1700             loadOperand(Special.getOp2(obj), EBP);
1701             asm.emit2_Reg_Reg(x86.MOV_r_r32, ESP, EBX);
1702             asm.emit2_Reg(x86.JMP_r, ECX);
1703         } else if (o instanceof Special.POP_FP32) {
1704             asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1705             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1706             asm.emitShort_Reg(x86.POP_r, EAX);
1707             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1708         } else if (o instanceof Special.POP_FP64) {
1709             asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
1710             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1711             asm.emitShort_Reg(x86.POP_r, EAX);
1712             asm.emitShort_Reg(x86.POP_r, EDX);
1713             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1714         } else if (o instanceof Special.PUSH_FP32) {
1715             loadOperand(Special.getOp2(obj), EAX);
1716             asm.emitShort_Reg(x86.PUSH_r, EAX);
1717             asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1718             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1719         } else if (o instanceof Special.PUSH_FP64) {
1720             loadOperand(Special.getOp2(obj), EAX);
1721             asm.emitShort_Reg(x86.PUSH_r, EDX);
1722             asm.emitShort_Reg(x86.PUSH_r, EAX);
1723             asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1724             asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1725         } else if (o instanceof Special.GET_EAX) {
1726             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1727         } else if (o instanceof Special.PUSHARG_I || o instanceof Special.PUSHARG_P) {
1728             loadOperand(Special.getOp2(obj), EAX);
1729             asm.emitShort_Reg(x86.PUSH_r, EAX);
1730         } else if (o instanceof Special.INVOKE_L || o instanceof Special.INVOKE_P) {
1731             loadOperand(Special.getOp2(obj), EAX);
1732             asm.emit2_Reg(x86.CALL_r, EAX);
1733             storeOperand((RegisterOperand) Special.getOp1(obj), EAX);
1734         } else if (o instanceof Special.ISEQ) {
1735             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
1736             asm.emitCJUMP_Short(x86.JNE, (byte)0);
1737             int cloc = asm.getCurrentOffset();
1738             asm.emitShort_Reg(x86.INC_r32, ECX);
1739             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1740             storeOperand((RegisterOperand) Special.getOp1(obj), ECX);
1741         } else if (o instanceof Special.ISGE) {
1742             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
1743             asm.emitCJUMP_Short(x86.JL, (byte)0);
1744             int cloc = asm.getCurrentOffset();
1745             asm.emitShort_Reg(x86.INC_r32, ECX);
1746             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1747             storeOperand((RegisterOperand) Special.getOp1(obj), ECX);
1748         }
1749         else {
1750             Assert.UNREACHABLE(obj.toString());
1751         }
1752         this.handled = true;
1753     }
1754     /***
1755      * @see joeq.Compiler.Quad.QuadVisitor#visitStoreCheck(joeq.Compiler.Quad.Quad)
1756      */
1757     public void visitStoreCheck(Quad obj) {
1758         if (TRACE) System.out.println(this+" StoreCheck: "+obj);
1759         loadOperand(StoreCheck.getElement(obj), EAX);
1760         asm.emitShort_Reg(x86.PUSH_r, EAX);
1761         loadOperand(StoreCheck.getRef(obj), EAX);
1762         asm.emitShort_Reg(x86.PUSH_r, EAX);
1763         emitCallRelative(TypeCheck._arrayStoreCheck);
1764         this.handled = true;
1765     }
1766     /***
1767      * @see joeq.Compiler.Quad.QuadVisitor#visitTableSwitch(joeq.Compiler.Quad.Quad)
1768      */
1769     public void visitTableSwitch(Quad obj) {
1770         if (TRACE) System.out.println(this+" TableSwitch: "+obj);
1771         int low = TableSwitch.getLow(obj).getValue();
1772         BasicBlockTableOperand targets = TableSwitch.getTargetTable(obj);
1773         //int high = low+targets.size()-1;
1774         loadOperand(TableSwitch.getSrc(obj), EAX);
1775         if (low != 0)
1776             asm.emitARITH_Reg_Imm(x86.SUB_r_i32, EAX, low);
1777         asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, targets.size());
1778         branchHelper(BytecodeVisitor.CMP_AE, TableSwitch.getDefault(obj).getTarget());
1779         asm.emitCALL_rel32(x86.CALL_rel32, 0);
1780         int cloc = asm.getCurrentOffset();
1781         asm.emitShort_Reg(x86.POP_r, ECX);
1782         // val from table + abs position in table
1783         asm.emit2_Reg_Mem(x86.LEA, EDX, ECX, EAX, SCALE_4, 127);
1784         int cloc2 = asm.getCurrentOffset();
1785         asm.emitARITH_Reg_Mem(x86.ADD_r_m32, EDX, -4, EDX);
1786         asm.emit2_Reg(x86.JMP_r, EDX);
1787         asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc+4));
1788         for (int i=0; i<targets.size(); ++i) {
1789             BasicBlock target = targets.get(i);
1790             if (asm.containsTarget(target)) {
1791                 int offset = asm.getBranchTarget(target) - asm.getCurrentOffset() + 4;
1792                 asm.emitDATA(offset);
1793             } else {
1794                 asm.emitDATA(0x77777777);
1795                 asm.recordForwardBranch(4, target);
1796             }
1797         }
1798         this.handled = true;
1799     }
1800     /***
1801      * @see joeq.Compiler.Quad.QuadVisitor#visitUnary(joeq.Compiler.Quad.Quad)
1802      */
1803     public void visitUnary(Quad obj) {
1804         if (TRACE) System.out.println(this+" Unary: "+obj);
1805         loadOperand(Unary.getSrc(obj), EAX);
1806         Unary op = (Unary) obj.getOperator();
1807         if (op instanceof Unary.NEG_I) {
1808             asm.emit2_Reg(x86.NEG_r32, EAX);
1809         } else if (op instanceof Unary.NEG_L) {
1810             asm.emit2_Reg(x86.NEG_r32, EDX);
1811             asm.emit2_Reg(x86.NEG_r32, EAX);
1812             asm.emitARITH_Reg_Imm(x86.SBB_r_i32, EDX, 0);
1813         } else if (op instanceof Unary.NEG_F) {
1814             asm.emitShort_Reg(x86.PUSH_r, EAX);
1815             asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1816             asm.emit2(x86.FCHS);
1817             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1818             asm.emitShort_Reg(x86.POP_r, EAX);
1819         } else if (op instanceof Unary.NEG_D) {
1820             asm.emitShort_Reg(x86.PUSH_r, EDX);
1821             asm.emitShort_Reg(x86.PUSH_r, EAX);
1822             asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1823             asm.emit2(x86.FCHS);
1824             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1825             asm.emitShort_Reg(x86.POP_r, EAX);
1826             asm.emitShort_Reg(x86.POP_r, EDX);
1827         } else if (op instanceof Unary.INT_2LONG) {
1828             asm.emit1(x86.CWD);
1829         } else if (op instanceof Unary.INT_2FLOAT) {
1830             asm.emitShort_Reg(x86.PUSH_r, EAX);
1831             asm.emit2_Mem(x86.FILD_m32, 0, ESP);
1832             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1833             asm.emitShort_Reg(x86.POP_r, EAX);
1834         } else if (op instanceof Unary.INT_2DOUBLE) {
1835             asm.emitShort_Reg(x86.PUSH_r, EAX);
1836             asm.emit2_Mem(x86.FILD_m32, 0, ESP);
1837             asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1838             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1839             asm.emitShort_Reg(x86.POP_r, EAX);
1840             asm.emitShort_Reg(x86.POP_r, EDX);
1841         } else if (op instanceof Unary.LONG_2INT) {
1842         } else if (op instanceof Unary.LONG_2FLOAT) {
1843             asm.emitShort_Reg(x86.PUSH_r, EDX);
1844             asm.emitShort_Reg(x86.PUSH_r, EAX);
1845             asm.emit2_Mem(x86.FILD_m64, 0, ESP);
1846             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1847             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1848             asm.emitShort_Reg(x86.POP_r, EAX);
1849         } else if (op instanceof Unary.LONG_2DOUBLE) {
1850             asm.emitShort_Reg(x86.PUSH_r, EDX);
1851             asm.emitShort_Reg(x86.PUSH_r, EAX);
1852             asm.emit2_Mem(x86.FILD_m64, 0, ESP);
1853             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1854             asm.emitShort_Reg(x86.POP_r, EAX);
1855             asm.emitShort_Reg(x86.POP_r, EDX);
1856         } else if (op instanceof Unary.FLOAT_2INT) {
1857             asm.emitShort_Reg(x86.PUSH_r, EAX);
1858             asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1859             toIntHelper();
1860             asm.emitShort_Reg(x86.POP_r, EAX);
1861         } else if (op instanceof Unary.FLOAT_2LONG) {
1862             asm.emitShort_Reg(x86.PUSH_r, EAX);
1863             asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1864             asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1865             toLongHelper();
1866             asm.emitShort_Reg(x86.POP_r, EAX);
1867             asm.emitShort_Reg(x86.POP_r, EDX);
1868         } else if (op instanceof Unary.FLOAT_2DOUBLE) {
1869             asm.emitShort_Reg(x86.PUSH_r, EAX);
1870             asm.emit2_Mem(x86.FLD_m32, 0, ESP);
1871             asm.emit2_Reg_Mem(x86.LEA, ESP, -4, ESP);
1872             asm.emit2_Mem(x86.FSTP_m64, 0, ESP);
1873             asm.emitShort_Reg(x86.POP_r, EAX);
1874             asm.emitShort_Reg(x86.POP_r, EDX);
1875         } else if (op instanceof Unary.DOUBLE_2INT) {
1876             asm.emitShort_Reg(x86.PUSH_r, EDX);
1877             asm.emitShort_Reg(x86.PUSH_r, EAX);
1878             asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1879             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1880             toIntHelper();
1881             asm.emitShort_Reg(x86.POP_r, EAX);
1882         } else if (op instanceof Unary.DOUBLE_2LONG) {
1883             asm.emitShort_Reg(x86.PUSH_r, EDX);
1884             asm.emitShort_Reg(x86.PUSH_r, EAX);
1885             asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1886             toLongHelper();
1887             asm.emitShort_Reg(x86.POP_r, EAX);
1888             asm.emitShort_Reg(x86.POP_r, EDX);
1889         } else if (op instanceof Unary.DOUBLE_2FLOAT) {
1890             asm.emitShort_Reg(x86.PUSH_r, EDX);
1891             asm.emitShort_Reg(x86.PUSH_r, EAX);
1892             asm.emit2_Mem(x86.FLD_m64, 0, ESP);
1893             asm.emit2_Reg_Mem(x86.LEA, ESP, 4, ESP);
1894             asm.emit2_Mem(x86.FSTP_m32, 0, ESP);
1895             asm.emitShort_Reg(x86.POP_r, EAX);
1896         } else if (op instanceof Unary.INT_2BYTE) {
1897             asm.emit3_Reg_Reg(x86.MOVSX_r_r8, EAX, AL);
1898         } else if (op instanceof Unary.INT_2SHORT) {
1899             asm.emit3_Reg_Reg(x86.MOVSX_r_r16, EAX, AX);
1900         } else if (op instanceof Unary.INT_2CHAR) {
1901             asm.emit3_Reg_Reg(x86.MOVZX_r_r16, EAX, AX);
1902         } else if (op instanceof Unary.FLOAT_2INTBITS) {
1903             // do nothing.
1904         } else if (op instanceof Unary.INTBITS_2FLOAT) {
1905             // do nothing.
1906         } else if (op instanceof Unary.DOUBLE_2LONGBITS) {
1907             // do nothing.
1908         } else if (op instanceof Unary.LONGBITS_2DOUBLE) {
1909             // do nothing.
1910         } else if (op instanceof Unary.OBJECT_2ADDRESS) {
1911             // do nothing.
1912         } else if (op instanceof Unary.ADDRESS_2OBJECT) {
1913             // do nothing.
1914         } else if (op instanceof Unary.INT_2ADDRESS) {
1915             // do nothing.
1916         } else if (op instanceof Unary.ADDRESS_2INT) {
1917             // do nothing.
1918         } else if (op instanceof Unary.ISNULL_P) {
1919             asm.emitShort_Reg_Imm(x86.MOV_r_i32, ECX, 0);
1920             asm.emitARITH_Reg_Imm(x86.CMP_r_i32, EAX, 0);
1921             asm.emitCJUMP_Short(x86.JNE, (byte)0);
1922             int cloc = asm.getCurrentOffset();
1923             asm.emitShort_Reg(x86.INC_r32, ECX);
1924             asm.patch1(cloc-1, (byte)(asm.getCurrentOffset()-cloc));
1925             asm.emit2_Reg_Reg(x86.MOV_r_r32, EAX, ECX);
1926         }
1927         else {
1928             Assert.UNREACHABLE(obj.toString());
1929         }
1930         storeOperand(Binary.getDest(obj), EAX);
1931         this.handled = true;
1932     }
1933     private void toIntHelper() {
1934         // check for NaN
1935         emitFLD64(MathSupport._maxint);
1936         asm.emit2_FPReg(x86.FUCOMIP, 1);
1937         asm.emitCJUMP_Short(x86.JP, (byte)0);
1938         int cloc1 = asm.getCurrentOffset();
1939         // check for >=MAX_INT
1940         asm.emitCJUMP_Short(x86.JBE, (byte)0);
1941         int cloc2 = asm.getCurrentOffset();
1942         // check for <=MIN_INT
1943         emitFLD64(MathSupport._minint);
1944         asm.emit2_FPReg(x86.FUCOMIP, 1);
1945         asm.emitCJUMP_Short(x86.JAE, (byte)0);
1946         int cloc3 = asm.getCurrentOffset();
1947         // default case
1948         asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
1949         {   // set rounding mode to round-towards-zero
1950             asm.emit2_Mem(x86.FNSTCW, 4, ESP);
1951             asm.emit2_Mem(x86.FNSTCW, 0, ESP);
1952             asm.emitARITH_Mem_Imm(x86.OR_m_i32, 4, ESP, 0x0c00);
1953             asm.emit2(x86.FNCLEX);
1954             asm.emit2_Mem(x86.FLDCW, 4, ESP);
1955         }
1956         asm.emit2_Mem(x86.FISTP_m32, 8, ESP);
1957         {
1958             // restore fpu control word
1959             asm.emit2(x86.FNCLEX);
1960             asm.emit2_Mem(x86.FLDCW, 0, ESP);
1961         }
1962         asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
1963         asm.emitJUMP_Short(x86.JMP, (byte)0);
1964         int cloc4 = asm.getCurrentOffset();
1965         asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
1966         // NaN -> 0
1967         asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, 0);
1968         asm.emitJUMP_Short(x86.JMP, (byte)0);
1969         int cloc5 = asm.getCurrentOffset();
1970         asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
1971         // >=MAX_INT -> MAX_INT
1972         asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, Integer.MAX_VALUE);
1973         asm.emitJUMP_Short(x86.JMP, (byte)0);
1974         int cloc6 = asm.getCurrentOffset();
1975         asm.patch1(cloc3-1, (byte)(asm.getCurrentOffset()-cloc3));
1976         // <=MIN_INT -> MIN_INT
1977         asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, Integer.MIN_VALUE);
1978         asm.patch1(cloc5-1, (byte)(asm.getCurrentOffset()-cloc5));
1979         asm.patch1(cloc6-1, (byte)(asm.getCurrentOffset()-cloc6));
1980         asm.emit2_FPReg(x86.FFREE, 0);
1981         asm.patch1(cloc4-1, (byte)(asm.getCurrentOffset()-cloc4));
1982         this.handled = true;
1983     }
1984     private void toLongHelper() {
1985         // check for NaN
1986         emitFLD64(MathSupport._maxlong);
1987         asm.emit2_FPReg(x86.FUCOMIP, 1);
1988         asm.emitCJUMP_Short(x86.JP, (byte)0);
1989         int cloc1 = asm.getCurrentOffset();
1990         // check for >=MAX_LONG
1991         asm.emitCJUMP_Short(x86.JBE, (byte)0);
1992         int cloc2 = asm.getCurrentOffset();
1993         // check for <=MIN_LONG
1994         emitFLD64(MathSupport._minlong);
1995         asm.emit2_FPReg(x86.FUCOMIP, 1);
1996         asm.emitCJUMP_Short(x86.JAE, (byte)0);
1997         int cloc3 = asm.getCurrentOffset();
1998         // default case
1999         asm.emit2_Reg_Mem(x86.LEA, ESP, -8, ESP);
2000         {   // set rounding mode to round-towards-zero
2001             asm.emit2_Mem(x86.FNSTCW, 4, ESP);
2002             asm.emit2_Mem(x86.FNSTCW, 0, ESP);
2003             asm.emitARITH_Mem_Imm(x86.OR_m_i32, 4, ESP, 0x0c00);
2004             asm.emit2(x86.FNCLEX);
2005             asm.emit2_Mem(x86.FLDCW, 4, ESP);
2006         }
2007         asm.emit2_Mem(x86.FISTP_m64, 8, ESP);
2008         {
2009             // restore fpu control word
2010             asm.emit2(x86.FNCLEX);
2011             asm.emit2_Mem(x86.FLDCW, 0, ESP);
2012         }
2013         asm.emit2_Reg_Mem(x86.LEA, ESP, 8, ESP);
2014         asm.emitJUMP_Short(x86.JMP, (byte)0);
2015         int cloc4 = asm.getCurrentOffset();
2016         asm.patch1(cloc1-1, (byte)(asm.getCurrentOffset()-cloc1));
2017         // NaN -> 0
2018         asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, 0);
2019         asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, 0);
2020         asm.emitJUMP_Short(x86.JMP, (byte)0);
2021         int cloc5 = asm.getCurrentOffset();
2022         asm.patch1(cloc2-1, (byte)(asm.getCurrentOffset()-cloc2));
2023         // >=MAX_LONG -> MAX_LONG
2024         asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, (int)Long.MAX_VALUE);
2025         asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, (int)(Long.MAX_VALUE>>32));
2026         asm.emitJUMP_Short(x86.JMP, (byte)0);
2027         int cloc6 = asm.getCurrentOffset();
2028         asm.patch1(cloc3-1, (byte)(asm.getCurrentOffset()-cloc3));
2029         // <=MIN_LONG -> MIN_LONG
2030         asm.emit2_Mem_Imm(x86.MOV_m_i32, 0, ESP, (int)Long.MIN_VALUE);
2031         asm.emit2_Mem_Imm(x86.MOV_m_i32, 4, ESP, (int)(Long.MIN_VALUE>>32));
2032         asm.patch1(cloc5-1, (byte)(asm.getCurrentOffset()-cloc5));
2033         asm.patch1(cloc6-1, (byte)(asm.getCurrentOffset()-cloc6));
2034         asm.emit2_FPReg(x86.FFREE, 0);
2035         asm.patch1(cloc4-1, (byte)(asm.getCurrentOffset()-cloc4));
2036         this.handled = true;
2037     }
2038     /***
2039      * @see joeq.Compiler.Quad.QuadVisitor#visitZeroCheck(joeq.Compiler.Quad.Quad)
2040      */
2041     public void visitZeroCheck(Quad obj) {
2042         if (TRACE) System.out.println(this+" ZeroCheck: "+obj);
2043         asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EAX, EAX);
2044         asm.emitARITH_Reg_Reg(x86.XOR_r_r32, EDX, EDX);
2045         loadOperand(ZeroCheck.getSrc(obj), EBX);
2046         asm.emit2_Reg(x86.IDIV_r32, EBX);
2047         this.handled = true;
2048     }
2049     boolean handled;
2050     /***
2051      * @see joeq.Compiler.Quad.QuadVisitor#visitQuad(joeq.Compiler.Quad.Quad)
2052      */
2053     public void visitQuad(Quad obj) {
2054         Assert._assert(handled, obj.toString());
2055     }
2056 
2057     public static void main(String[] args) {
2058         HostedVM.initialize();
2059         CodeAddress.FACTORY = joeq.Bootstrap.BootstrapCodeAddress.FACTORY;
2060         HeapAddress.FACTORY = joeq.Bootstrap.BootstrapHeapAddress.FACTORY;
2061         ClassLibInterface.useJoeqClasslib(true);
2062         CodeAllocator.initializeCompiledMethodMap();
2063         BootstrapCodeAllocator bca = BootstrapCodeAllocator.DEFAULT;
2064         DefaultCodeAllocator.default_allocator = bca;
2065         //CodeAddress.FACTORY = BootstrapCodeAddress.FACTORY = new BootstrapCodeAddressFactory(bca);
2066         bca.init();
2067         ObjectTraverser obj_trav = ClassLibInterface.DEFAULT.getObjectTraverser();
2068         Reflection.obj_trav = obj_trav;
2069         obj_trav.initialize();
2070         SinglePassBootImage objmap = SinglePassBootImage.DEFAULT;
2071         
2072         // enable allocations
2073         objmap.enableAllocations();
2074         
2075         String className = args[0];
2076         jq_Class c = (jq_Class) jq_Type.parseType(className);
2077         c.cls_initialize();
2078         
2079         ALWAYS_TRACE = true;
2080         x86Assembler.TRACE = true;
2081         
2082         Iterator i = Arrays.asList(c.getDeclaredStaticMethods()).iterator();
2083         i = new AppendIterator(i, Arrays.asList(c.getDeclaredInstanceMethods()).iterator());
2084         while (i.hasNext()) {
2085             jq_Method m = (jq_Method) i.next();
2086             if (m.getBytecode() != null) {
2087                 ControlFlowGraph cfg = CodeCache.getCode(m);
2088                 SimpleCompiler compiler = new SimpleCompiler(cfg);
2089                 jq_CompiledCode cc = compiler.compile();
2090                 m.setDefaultCompiledVersion(cc);
2091             }
2092         }
2093     }
2094 
2095 }